Есть класс A
partial class A {
public event EventHandler MyHandler;
public A() { };
}
partial class A {
protected void H1(object sender, EventArgs e) { Something1(); };
protected void B1() { MyHandler += H1; }
}
partial class A {
protected void H2(object sender, EventArgs e) { Something2(); };
protected void B2() { MyHandler += H2; }
}
partial class A {
protected void H3(object sender, EventArgs e) { Something3(); };
protected void B3() { MyHandler += H3; }
}
Мне необходимо, чтобы разделяемый класс вызывал метод B[N] в конструкторе, при этом не меняя первое определение. Поясню, у меня есть куча файлов cs, каждый из них определяет логику поведения экземпляра, подключая их и отключая - класс A ведёт себя по разному. Иногда нужно чтобы модуль подключался к событиям этого класса при его создании. Как это сделать?
Как решал проблему: Как вариант использовал атрибут
public class AutoInitialize : Attribute { }
и в методы добавлять атрибут
[AutoInitialize]
public void B1() { }
[AutoInitialize]
public void B2() { }
[AutoInitialize]
public void B3() { }
а в основной конструктор вставляем текст
MethodInfo[] methods = GetType()
.GetMethods()
.Where(x => x.GetCustomAttribute(typeof(AutoInitialize)) != null && !x.IsStatic).ToArray();
foreach (MethodInfo method in methods)
{
method.Invoke(this, new object[0]);
/* try { method.Invoke(this, new object[0]); } catch { } */
}
Ответ
В комментариях объяснить свою точку зрения не удалось, поэтому описываю здесь.
Я вижу решение следующим образом.
Создаем интерфейс, метод которого будет использован при инициализации.
interface IInitializer
{
void Initialize(IA a); // аналог методов B1, B2, B3
}
// нужен для доступа к членам класса A
interface IA
{
event EventHandler MyHandler;
}
Создаем реализации.
class Initializer1 : IInitializer
{
public B(IA a)
{
a.MyHandler += (s, e) => Something1();
}
}
class Initializer2 : IInitializer { ... }
Вызываем метод для всех реализаций.
class A : IA
{
public A()
{
var initializers = new IInitializer[] { new Initializer1(), new Initializer2(), ... }
foreach (var i in initializers)
{
i.Initialize(this);
}
}
}
Насколько я понимаю, вас смущает необходимость перечислять все инициализаторы в классе A. Т.е. при создании нового инициализатора придется менять класс A. Для того, чтобы избежать этого можно воспользоваться каким-нибудь контейнером. Например, MEF
Рассмотрим пример с MEF. Сначала пометим реализации атрибутом Export
[Export(typeof(IInitializer))]
class Initializer1 : IInitializer { ... }
[Export(typeof(IInitializer))]
class Initializer2 : IInitializer { ... }
Потом подправим класс A
class A : IA
{
public A()
{
// Выбор каталога зависит от ваших нужд. В данном случае предполагается, что все реализации лежат в этой же сборке.
using (var catalog = new AssemblyCatalog(GetType().Assembly))
using (var container = new CompositionContainer(catalog))
{
var initializers = container.GetExportedValues
Писал без VS, так что за компилируемость не ручаюсь.
Комментариев нет:
Отправить комментарий