Possible Duplicate:
Casting an object to two interfa开发者_如何学Cces at the same time, to call a generic method
I'm fairly sure you can't do this so I'm wondering if there's a workaround, but I need/want to cast an object to represent multiple interfaces for use with generic constraints. For example:
public void Foo<T>(T t) where T : IInterfaceA, IInterfaceB
{
}
If I have an object I want to say something like var t = (IInterfaceA | IInterfaceB)someObj;
so I can pass t
into this method.
Is there a nifty way of doing this? I'm using C# 3.5 so no dynamic available, but if it's possible with dynamic please post it anyway.
EDIT
Despite the answer below, I would say the better solution is the one that most other answers point to. (This assumes that you can redefine the multiple classes that implement both interfaces.)
Create an interface that inherits from both InterfaceA and InterfaceB, then, for all classes that implement interfaces A and B, replace those interfaces with the new one. Before:
class SomeClass : IInterfaceA, IInterfaceB { }
class AnotherClass : IInterfaceA, IInterfaceB { }
class AdditionalClass : IInterfaceA, IInterfaceB { }
After:
interface IInterfaceC : IInterfaceA, IInterfaceB { }
class SomeClass : IInterfaceC { }
class AnotherClass : IInterfaceC { }
class AdditionalClass : IInterfaceC { }
The implementation of Foo is then fairly trivial. And, again, since you don't know at compile time what type you have on hand, you may be able just to declare it as
public void Foo(IInterfaceC someObj) { }
END EDIT
You can do it using reflection, though some will say that this isn't particularly "nifty":
public class FooClass
{
public void Foo<T> (T t) where T : IInterfaceA, IInterfaceB
{
//... do your thing here
}
private static void Example(object someObj)
{
var type = someObj.GetType();
if(typeof(IInterfaceA).IsAssignableFrom(type) && typeof(IInterfaceB).IsAssignableFrom(type))
{
var genericMethod = typeof(FooClass).GetMethod("Foo");
var constructedMethod = genericMethod.MakeGenericMethod(type);
var instance = new FooClass();
var result = constructedMethod.Invoke(instance, new [] { someObj });
Assert.IsNull(result);
}
}
}
you could also do this, which could allow you to make Foo non-generic. It's also fairly ugly, so I would hide this ugliness by making it private:
private void PrivateFoo(IInterfaceA objA, IInterfaceB objB)
{
if (!ReferenceEquals(objA, objB))
throw new ArgumentException("objA and objB must refer to the same object");
//... do your thing here
}
public void Foo(object someObj)
{
PrivateFoo((IInterfaceA)someObj, (IInterfaceB)someObj);
}
public void Foo<T>(T t) where T : IInterfaceA, IInterfaceB{}
{
// T already implements IInterfaceA and IInterfaceB, just call the methods.
t.MethodFromA();
t.MethodFromB();
}
T t = (T)someObj;
This will cast the object to T, not the two interfaces... so it's up to you to make sure that'll work.
IInterfaceA tA = (IInterfaceA)someObj;
IInterfaceB tB = (IInterfaceB)someObj;
Two references to the one instance.
No, there is no way.
The only thing that comes close is to create another interface the inherits those two interfaces. But then all your classes need to implement that third interface instead of the two others, so in most circumstances, this is not practical.
Just cast it to that interface you need at that moment.
UPDATE:
The only way I can see is to create a container class that implements those interfaces:
class Container : IInterfaceA, IInterfaceB
{
private object _obj;
public Container(object obj)
{
// Check that the object really implements those two interfaces.
_obj = obj;
}
void IInterfaceA.Method1()
{
((IInterfaceA)_obj).Method1();
}
// And so on for all methods of the interfaces.
}
One possible way to do this is have inheritance of interfaces. Move the common functionality, to the parent interface, which should be used in above scenarios.
You may be able to restructure your inheritance to achieve your goal.
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
public interface IList : ICollection, IEnumerable
Note that ArrayList inerits from IList, which inherits from two interfaces already included in Arraylist.
精彩评论