Есть ли простой синтаксис для проделывания этого (без написания тупого кода вручную и использования генераторов из библиотек для тестирования)?
т.е.
public class ObservableMyClass
{
public void MyMethod1() { ... }
public void MyProperty1 { get; set; }
}
public class MyClass
{
ObservableMyClass myObject;
public MyClass(ObservableMyClass myObject) { this.myObject = myObject; }
public void MyMethod1() { myObject.MyMethod1(); }
public void MyProperty1 { get {return myObject.MyProperty1;} set{myObject.MyProperty1 = value;} }
}
Не хотелось бы руками писать для каждого метода и свойства обёртку, и много внешнего кода тянуть.
Наследование мне нельзя, потому что объекты MyClass у меня связаны с объектами ObservableMyClass отношением N к 1, а не 1:1
Здравствуйте, Эйнсток Файр, Вы писали:
ЭФ>Есть ли простой синтаксис для проделывания этого (без написания тупого кода вручную и использования генераторов из библиотек для тестирования)?
Как подсказал коллега RushDevion можно использовать Mixins из библиотек с DynamicProxy. Того же Castle.
Приблизительно решение выглядит так.
Пусть у нас есть 2 класса, которые мы хотим обернуть в один агрегатор:
public class ObservableMyClass1
{
public void MyMethod1() { Console.WriteLine("1"); }
public int MyProperty1 { get; set; }
}
public class ObservableMyClass2
{
public void MyMethod2() { Console.WriteLine("2"); }
public int MyProperty2 { get; set; }
}
Первым делом выделяем интерфейсы для этих классов (это можно сделать в той же студии через рефакторинг).
Т.к. нам нужно будет сохранить связь между интерфейсом и реализаций, я сделал специальный атрибут, которым разметил интерфесы (можно сделать иначе — просто искать через рефлексию классы, в которых реализуются эти интерфейсы или задать связь в коде, ... — куча вариантов).
public class ImplementationAttribute : Attribute
{
public ImplementationAttribute(Type type)
{
Type = type;
}
public Type Type { get; set; }
}
[Implementation(typeof(ObservableMyClass1))]
public interface IObservableMyClass1
{
int MyProperty1 { get; set; }
void MyMethod1();
}
public class ObservableMyClass1 : IObservableMyClass1
{
public void MyMethod1() { Console.WriteLine("1"); }
public int MyProperty1 { get; set; }
}
[Implementation(typeof(ObservableMyClass2))]
public interface IObservableMyClass2
{
int MyProperty2 { get; set; }
void MyMethod2();
}
public class ObservableMyClass2 : IObservableMyClass2
{
public void MyMethod2() { Console.WriteLine("2"); }
public int MyProperty2 { get; set; }
}
Для того, чтобы описать агрегатор используем множественное наследование в интерфейсах
public interface IMyClass : IObservableMyClass1, IObservableMyClass2
{
}
Собственно осталось сгенерировать proxy-класс, который будет реализовывать интерфейс IMyClass, но перенаправлять вызовы на реализации интерфейсов IObservableMyClass1 и IObservableMyClass2
public T GetMixedClass<T>() where T : class
{
var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions();
var type = typeof(T);
var interfaces = type.GetInterfaces();
foreach (var interf in interfaces)
{
var imp = interf.GetCustomAttributes(typeof(ImplementationAttribute), true)
.OfType<ImplementationAttribute>().SingleOrDefault();
if (imp != null)
{
options.AddMixinInstance(Activator.CreateInstance(imp.Type));
}
}
return (T) generator.CreateClassProxy(typeof(object), new[] { typeof(T) }, options);
}
Всё, можем пользоваться:
var a = GetMixedClass<IMyClass>();
a.MyMethod1();
a.MyMethod2();