2010-02-24 2 views
3

У меня есть методы:Как реорганизовать перегруженные методы

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); 

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

ответ

1

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

+0

Да, это похоже на то, что я ищу, но я могу использовать 3.5 рамки. Можно ли имитировать его? спасибо за ссылку. – Steck

+0

Я сам не реализовал этот шаблон, но, когда вы разговариваете с коллегами, общими для этого являются использование шаблона двойной отправки. Это описано здесь -> http://www.garyshort.org/blog/archive/2008/02/11/double-dispatch-pattern.aspx. Надеюсь, это поможет – mattythomas2000

0

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

Хммм ...

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

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

4

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

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()); 
+0

Мой код также вызывается из дескрипторов свойств, поэтому требуется MyMethod (объект) или некоторый менеджер для правильного типа. Этот вопрос можно свести к вопросу о написании менеджера. – Steck

+0

В описании дескрипторов свойств вы говорите об атрибутах? Что вы пытаетесь сделать с кодом? Может возникнуть проблема с дизайном. –