Как реорганизовать перегруженные методы - PullRequest
3 голосов
/ 24 февраля 2010

У меня есть методы:

public MyReturnType MyMethod(Class1 arg)
{
 //implementation
}

public MyReturnType MyMethod(Class2 arg)
{
 //implementation
}

//...

public MyReturnType MyMethod(ClassN arg)
{
 //implementation
}

десятичное, строковое, DateTime в [Class1, ..., ClassN]
и один общий метод:

public MyReturnType MyMethod(object obj)
{
 if(obj == null)
  throw new ArgumentNullException("obj");
 if(obj is MyClass1)
  return MyMethod((Class1)obj);
 if(obj is MyClass2)
  return MyMethod((Class2)obj);
 //...
 if(obj is MyClassN)
  return MyMethod((ClassN)obj);
 return MyMethod(obj.ToString()); //MyMethod(string) implemented.
}

Как я могу изменить этот код? Я могу использовать атрибуты и компонентную модель, что-то вроде этого:

public class MyAttribute : Attribute
{
 public Type Type { get; set; }
}

public MyReturnType MyMethod(object obj)
{
    if(obj == null)
        throw new ArgumentNullException("obj");
 var protperty = TypeDescriptor.GetProperties(this, new Attribute[] { new MyAttribute() })
  .Cast<PropertyDescriptor>().FirstOrDefault(x =>
   x.GetAttribute<MyAttribute>().Type.IsInstanceOfType(obj));
 if (protperty != null)
  return protperty.GetValue(obj) as MyReturnType;
 return MyMethod(obj.ToString());
}

но это выглядит довольно сложно для понимания и может создать некоторые ошибки. Например, если кто-то объявит метод, такой как

[MyAttribute(Type = ClassNplus1)]
public NotMyReturnType MyMethod(ClassNplus1 arg);

Любые другие идеи, как создать расширяемую систему, где добавление нового класса требуется только для добавления одного метода? (добавить код в одном месте)

Ответы [ 3 ]

4 голосов
/ 24 февраля 2010

Похоже, вам нужно использовать универсальные методы:

public MyReturnType MyMethod<T>(T arg)
{
    // implementation
}

Приятно, что вы также можете ограничить T следующим образом:

public MyReturnType MyMethod<T>(T arg) where T : MyClassBase
{
    // implementation
}

Во втором случае вы можете обращаться с T так, как если бы это был фактический MyClassBase, но вы можете свободно передавать любой объект, если он (или является производным) MyClassBase. Это также работает для интерфейсов.

Вы вызываете этот метод так:

MyMethod(new MyClass1());
MyMethod(new MyClass2());
MyMethod(new MyClass3());

Компилятор достаточно умен, чтобы знать, какой это тип, поэтому вам не нужно передавать ему тип T, но иногда вам нужно явно объявить его при вызове метода, например:

MyMethod<MyClass1>(new MyClass1());
MyMethod<MyClass2>(new MyClass2());
MyMethod<MyClass3>(new MyClass3());
1 голос
/ 24 февраля 2010

Я считаю, что то, что вы пытаетесь сделать, называется множественной рассылкой (кто-то, пожалуйста, исправьте меня, если я ошибаюсь), и это недоступно в текущих версиях .Net Framework.Однако он вводится в .Net 4.0 через ключевое слово dynamic -> http://blogs.msdn.com/laurionb/archive/2009/08/13/multimethods-in-c-4-0-with-dynamic.aspx.

0 голосов
/ 24 февраля 2010

Вы можете использовать Generics и Attributes для описания метаданных о классе Generics, скорее всего, очистит ваши операторы if

Ммм ...

public class MyClass<T>
{
   public OtherClass ReturnSomething(T checkThisType)
   {
   }
}

Извините, я мог бы быть более информативным. Надеюсь, это поможет.

...