Как можно улучшить этот код?
Интересует улучшение реализации интерфейса IValueChangedEventArgsFactory - класса ValueChangedEventArgsFactory. Возможно ли сделать обобщение? Мои попытки не дают результата. Обязательно не использовать рефлексию.
enum DataType
{
INT16,
UINT16,
// И еще типы есть
}
interface IValueChangedEventArgsFactory
{
IValueChangedEventArgs GetValueChangedEventArgs(string address, DataType dataType, OperateResult oldValue, OperateResult newValue);
}
class ValueChangedEventArgsFactory : IValueChangedEventArgsFactory
{
private IDictionary<DataType, Func<string, DataType, OperateResult, OperateResult, IValueChangedEventArgs>> factory;
public ValueChangedEventArgsFactory()
{
factory = new Dictionary<DataType, Func<string, DataType, OperateResult, OperateResult, IValueChangedEventArgs>>()
{
{ DataType.INT16, (string address, DataType dataType, OperateResult oldValue, OperateResult newValue)
=> new ValueChangedEventArgs<short>(address, dataType, oldValue, newValue) },
{ DataType.UINT16, (string address, DataType dataType, OperateResult oldValue, OperateResult newValue)
=> new ValueChangedEventArgs<ushort>(address, dataType, oldValue, newValue) }
};
}
public IValueChangedEventArgs GetValueChangedEventArgs(string address, DataType dataType, OperateResult oldValue, OperateResult newValue)
{
factory.TryGetValue(dataType, out Func<string, DataType, OperateResult, OperateResult, IValueChangedEventArgs> func);
return (func == null) ? throw new NotImplementedException() : func.Invoke(address, dataType, oldValue, newValue);
}
}
interface IValueChangedEventArgs
{
string Address { get; }
DataType DataType { get; }
}
interface IValueChangedEventArgs<T> : IValueChangedEventArgs
{
OperateResult<T> NewValue { get; }
OperateResult<T> OldValue { get; }
}
class ValueChangedEventArgs<T> : System.EventArgs, IValueChangedEventArgs<T>
{
public string Address { get; private set; }
public DataType DataType { get; private set; }
public OperateResult<T> OldValue { get; private set; }
public OperateResult<T> NewValue { get; private set; }
public ValueChangedEventArgs(string address, DataType dataType, OperateResult oldValue, OperateResult newValue)
{
Address = address;
DataType = dataType;
OldValue = (OperateResult<T>)oldValue;
NewValue = (OperateResult<T>)newValue;
}
}
class OperateResult
{
public bool IsSuccess;
}
class OperateResult<T> : OperateResult
{
public T Content;
}
public class Program
{
public static void Main()
{
var factory = new ValueChangedEventArgsFactory();
var oldValue = new OperateResult<short>() { Content = 1 };
var newValue = new OperateResult<short>() { Content = 2 };
var args = factory.GetValueChangedEventArgs(string.Empty, DataType.INT16, oldValue, newValue);
}
}
Ответы (1 шт):
Автор решения: Nova
→ Ссылка
В итоге получилось только так.
class Program
{
public static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new NinjectSettings { InjectNonPublic = true, InjectParentPrivateProperties = true });
kernel.Load(new Dependency());
var factory = kernel.Get<IValueChangedEventArgsFactory>("VCEAF");
var dataType = DataType.UINT16;
var oldValue = new OperateResult<ushort>() { Content = 1 };
var newValue = new OperateResult<ushort>() { Content = 2 };
var ea = factory.GetValueChangedEventArgs(string.Empty, dataType, oldValue, newValue);
}
}
internal interface IGetGenericFactory
{
IValueChangedEventArgsFactory GetGenericFactory(string factoryName);
}
class Dependency : NinjectModule
{
public override void Load()
{
Bind<IValueChangedEventArgsFactory>().To<ValueChangedEventArgsFactory>().Named("VCEAF");
Bind(typeof(IValueChangedEventArgsFactory)).To(typeof(ValueChangedEventArgsGenericFactory<short>)).Named("INT16");
Bind(typeof(IValueChangedEventArgsFactory)).To(typeof(ValueChangedEventArgsGenericFactory<ushort>)).Named("UINT16");
Bind<IGetGenericFactory>().ToFactory(() => new GenericFactoryProvider());
}
}
class GenericFactoryProvider : StandardInstanceProvider
{
protected override string GetName(MethodInfo methodInfo, object[] arguments)
=> (string)arguments[0];
protected override IConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
=> base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
}
enum DataType
{
INT16,
UINT16,
}
class ValueChangedEventArgsGenericFactory<T> : IValueChangedEventArgsFactory
{
public IValueChangedEventArgs GetValueChangedEventArgs(string address, DataType dataType, OperateResult oldValue, OperateResult newValue)
{
return new ValueChangedEventArgs<T>(address, dataType, oldValue, newValue);
}
}
interface IValueChangedEventArgsFactory
{
IValueChangedEventArgs GetValueChangedEventArgs(string address, DataType dataType, OperateResult oldValue, OperateResult newValue);
}
class ValueChangedEventArgsFactory : IValueChangedEventArgsFactory
{
private IGetGenericFactory genericFactory;
public ValueChangedEventArgsFactory(IGetGenericFactory getFactory)
{
this.genericFactory = getFactory;
}
public IValueChangedEventArgs GetValueChangedEventArgs(string address, DataType dataType, OperateResult oldValue, OperateResult newValue)
{
return genericFactory.GetGenericFactory(dataType.ToString()).GetValueChangedEventArgs(address, dataType, oldValue, newValue);
}
}
interface IValueChangedEventArgs
{
string Address { get; }
DataType DataType { get; }
}
interface IValueChangedEventArgs<T> : IValueChangedEventArgs
{
OperateResult<T> NewValue { get; }
OperateResult<T> OldValue { get; }
}
class ValueChangedEventArgs<T> : EventArgs, IValueChangedEventArgs<T>
{
public string Address { get; private set; }
public DataType DataType { get; private set; }
public OperateResult<T> OldValue { get; private set; }
public OperateResult<T> NewValue { get; private set; }
public ValueChangedEventArgs(string address, DataType dataType, OperateResult oldValue, OperateResult newValue)
{
Address = address;
DataType = dataType;
OldValue = (OperateResult<T>)oldValue;
NewValue = (OperateResult<T>)newValue;
}
}
class OperateResult
{
public bool IsSuccess;
}
class OperateResult<T> : OperateResult
{
public T Content;
}