Передача информации между базой данных SQL и ПЛК с использованием сторонних библиотек OPC.Добавление реализации интерфейса в ExpandoObject
Существует по существу две сделки.
Информация, переданная с ПЛК на сервер SQL, статически типизирована. Очень специфические данные фиксируются ПЛК и передаются в базу данных SQL.
Информация, передаваемая с сервера SQL в ПЛК, динамически типизируется и может быть ограничена одним свойством или сотнями.
ITransaction.cs
public interface ITransaction : INotifyPropertyChanged
{
short Response { get; set; }
bool Request { get; set; }
void Reset();
}
BaseTransaction.cs
internal abstract class BaseTransaction<T> : IDisposable
where T : class, INotifyPropertyChanged
{
private T _opcClient;
protected T OpcClient
{
get { return _opcClient; }
set
{
if (_opcClient != value)
{
OnOpcClientChanging();
_opcClient = value;
OnOpcClientChanged();
}
}
}
protected abstract void OnOpcClientPropertyChanged(object sender, PropertyChangedEventArgs e);
private void OnOpcClientChanged()
{
if (_opcClient != null)
{
_opcClient.PropertyChanged += OnOpcClientPropertyChanged;
OpcManager = new OpcManager(_opcClient);
}
}
private void OnOpcClientChanging()
{
if (_opcClient != null)
_opcClient.PropertyChanged -= OnOpcClientPropertyChanged;
}
}
StaticTransaction.cs
internal abstract class StaticTransaction<T> : BaseTransaction<T>
where T : class, ITransaction, new()
{
public StaticTransaction()
{
OpcClient = new T();
}
protected override void OnOpcClientPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Response":
ProcessResponse(OpcClient.Response);
break;
case "Request":
ProcessRequest(OpcClient.Request);
break;
}
}
}
DynamicTransaction.cs
internal abstract class DynamicTransaction : BaseTransaction<ExpandoObject>
{
protected new dynamic OpcClient
{
get { return base.OpcClient as dynamic; }
}
public DynamicTransaction()
{
dynamic opcClient = new ExpandoObject();
opcClient.Request = false;
opcClient.Response = 0;
// Access database, use IDictionary interface to add properties to ExpandoObject.
opcClient.Reset = new Action(Reset);
base.OpcClient = opcClient;
}
protected override void OnOpcClientPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Response":
ProcessResponse(OpcClient.Response);
break;
case "Request":
ProcessRequest(OpcClient.Request);
break;
}
}
private void Reset()
{
// Use IDictionary interface to reset dynamic properties to defaults.
OpcClient.Request = false;
OpcClient.Response = 0;
}
}
Как показано как StaticTransaction и DynamicTransaction имеют идентичные реализации OnOpcClientPropertyChanged среди других методов не показаны. Я хотел бы привести OnOpcClientPropertyChanged и другие методы в базовый класс, но мне не удалось это сделать, потому что базовый класс не знает свойств Response и Request, найденных в OpcClient. Можно ли каким-то образом привести интерфейс ITransaction в базовый класс и по-прежнему учитывать динамическую реализацию?
Это выглядит многообещающим, я все еще работаю через некоторые детали. Мой фактический прецедент несколько сложнее. ITransaction определяет метод, а также два свойства. Мне также нужно запустить событие PropertyChanged для всех свойств, а не только Response and Request. –
Я обновил 'DynamicTransactionObject', чтобы теперь запускать все свойства, а не только два из интерфейса (см. Обновленный' TrySetMember'). Для этого метода вы можете просто добавить его в класс так же, как вы добавили свойства. –
Это кажется близким, я предполагаю, что мне нужно вызвать OnPropertyChanged из явной реализации IDictionary?Я предполагаю, что TrySetMember используется ключевым словом dynamic? –