转换为多个接口

Ric*_*chK 8 c# generics casting

可能重复:同时
将对象转换为两个接口,以调用泛型方法

我很确定你不能这样做所以我想知道是否有一个解决方法,但我需要/想要一个对象来表示多个接口以用于泛型约束.例如:

public void Foo<T>(T t) where T : IInterfaceA, IInterfaceB
{
}
Run Code Online (Sandbox Code Playgroud)

如果我有一个对象,我想说出类似的话var t = (IInterfaceA | IInterfaceB)someObj;,我可以t转入这个方法.

这样做有一种漂亮的方式吗?我正在使用C#3.5,因此没有动态可用,但如果有可能动态请将其发布.

pho*_*oog 3

编辑

尽管有下面的答案,我想说更好的解决方案是大多数其他答案所指出的。(这假设您可以重新定义实现这两个接口的多个类。)

创建一个同时继承 InterfaceA 和 InterfaceB 的接口,然后,对于实现接口 A 和 B 的所有类,将这些接口替换为新接口。前:

class SomeClass : IInterfaceA, IInterfaceB { }
class AnotherClass : IInterfaceA, IInterfaceB { }
class AdditionalClass : IInterfaceA, IInterfaceB { }
Run Code Online (Sandbox Code Playgroud)

后:

interface IInterfaceC : IInterfaceA, IInterfaceB { }
class SomeClass : IInterfaceC { }
class AnotherClass : IInterfaceC { }
class AdditionalClass : IInterfaceC { }
Run Code Online (Sandbox Code Playgroud)

那么 Foo 的实现就相当简单了。而且,同样,由于您在编译时不知道手头有什么类型,因此您可以将其声明为

public void Foo(IInterfaceC someObj) { }
Run Code Online (Sandbox Code Playgroud)

结束编辑


您可以使用反射来做到这一点,尽管有些人会说这不是特别“漂亮”:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你也可以这样做,这可以让你使 Foo 成为非泛型。它也相当丑陋,所以我会通过将其设为私有来隐藏这种丑陋:

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);
}
Run Code Online (Sandbox Code Playgroud)