У меня есть объект o
который гарантируемый во времени выполнения быть одним из трех типов A
, B
, или C
, все из которых реализуют единый интерфейс I
. Я могу управлять I
, но нет A
, B
, или C
. (Таким образом я мог использовать пустой интерфейс маркера или так или иначе использовать в своих интересах общие черты в типах при помощи интерфейса, но я не могу добавить новые методы или изменить существующие в типах.)
У меня также есть ряд методов MethodA
, MethodB
, и MethodC
. Тип выполнения o
ищется и затем привык в качестве параметра к этим методам.
public void MethodA(A a) { ... }
public void MethodB(B b) { ... }
public void MethodC(C c) { ... }
Используя эту стратегию, прямо сейчас проверка должна быть выполнена на типе o
определить, какой метод должен быть вызван. Вместо этого я хотел бы просто иметь три перегруженных метода:
public void Method(A a) { ... } // these are all overloads of each other
public void Method(B b) { ... }
public void Method(C c) { ... }
Теперь я позволяю C# сделать отправку вместо того, чтобы делать его вручную сам. Это может быть сделано? Наивный простой подход не работает, конечно:
Не может разрешить метод 'Метод (объект)'. Кандидаты:
- освободите Метод (A)
- освободите Метод (B)
- освободите Метод (C)
Как насчет этого?
private Dictionary<Type, Action<I>> _mapping = new Dictionary<Type, Action<I>>
{
{ typeof(A), i => MethodA(i as A)},
{ typeof(B), i => MethodB(i as B)},
{ typeof(C), i => MethodC(i as C)},
};
private void ExecuteBasedOnType(object value)
{
if(_mapping.ContainsKey(value.GetType()))
_mapping(value.GetType())(value as I);
}
Если вы можете рефакторить это, переместите метод в интерфейс и каждый класс имеет свою реализацию:
I i = o as I;
i.Method();
Если 3 класса A, B и C реализуют интерфейс I, вам ничего не следует делать. Среда выполнения выбирает для вас правильный метод:
A a = new A();
class.Method(a); // will calll Method(A a)
B b = new B();
class.Method(b); // will call Method(B b)
Я не уверен на 100%, будет ли это работать в вашем сценарии, но похоже, что вы можете использовать частичные классы:
public interface IMethodCallable
{
public void Method();
}
public partial class A : IMethodCallable
{
public void Method()
{
....
}
}
затем для использования:
object o = getObject(); // we know this is A, B or C
((IMethodCallable)o).Method();
Предположительно O объявлен как тип / интерфейс, который я затем создал как b или c. Способ сделать это - иметь один общедоступный метод, который принимает параметр типа I, а затем выполняет свою логику в этом методе, например. вызовите частный метод AB или C.
Читая отредактированный пост, o относится к типу object, не забывайте четко понимать, когда вы говорите об объекте, потому что это не только тип c #, но и общий термин oop для экземпляра объекта класс.
Почему вы объявляете его как объект, а не как i, может это будет что-то еще позже?
Если это так, чтобы использовать ваши перегруженные методы, вам придется распаковать его перед вызовом метода. например
if (o.GetType() == typeof(a))
{
oa = (a)o;
Method(oa);
}
else if(o.GetType() == typeof(b))
{
...
}
И т. Д.
В качестве альтернативы, если вы заставите метод принимать параметр типа i, вы можете сделать что-то вроде:
i oi = (i)o;
Method(oi);
Но вам все равно нужно будет сделать что-то вроде первого примера в вашем общедоступном методе.