C# 只能通过接口访问类型为泛型参数类型的泛型类成员
本文关键字:参数 泛型 类型 成员 泛型类 访问类型 接口 | 更新日期: 2024-10-31 18:02:12
我有一个泛型类,它包含一个类型为参数类型的成员。
我希望只能通过它实现的接口之一访问此成员。
我只想通过此接口访问成员,而不是枚举它可能是的所有具体类型,是因为有大量这些类型。
所以具体地说,我想在该代码中找到与第 61 行的等效项(这是一个编译错误):
using System;
using System.Linq;
/* Interfaces */
public interface IArgumentClass
{
void IArgumentClassMethod();
}
public interface ISpecialArgumentClass
{
void ISpecialArgumentClassMethod();
}
public interface IContainerClass
{
void IContainerClassClassMethod();
}
/* Argument types */
public class ArgumentClass0 : IArgumentClass
{
public void IArgumentClassMethod(){}
}
public class SpecialArgumentClass0 : IArgumentClass, ISpecialArgumentClass
{
public void IArgumentClassMethod(){}
public void ISpecialArgumentClassMethod(){}
}
public class SpecialArgumentClass1 : IArgumentClass, ISpecialArgumentClass
{
public void IArgumentClassMethod() { }
public void ISpecialArgumentClassMethod() { }
}
/* Container types */
public class GenericContainer<T> : IContainerClass
where T : IArgumentClass, new()
{
public T t = new T();
public void IContainerClassClassMethod() { }
}
public class NonGenericContainer : IContainerClass
{
public void IContainerClassClassMethod(){}
}
/* main program */
public class Test
{
public static void Main()
{
// Instantiate
IContainerClass[] containers =
{
new GenericContainer<ArgumentClass0>(),
new GenericContainer<SpecialArgumentClass0>(),
new GenericContainer<SpecialArgumentClass1>(),
new NonGenericContainer()
};
// We want to call IContainerClassClassMethod methods on all instances:
foreach (IContainerClass container in containers)
container.IContainerClassClassMethod();
// We want to call ISpecialArgumentClassMethod on instances where it's possible:
foreach (IContainerClass container in containers)
{
if (container.GetType().IsGenericType && container.GetType().GetGenericTypeDefinition() == typeof(GenericContainer<>))
{
foreach (Type typeArgument in container.GetType().GetGenericArguments())
{
if (typeArgument.GetInterfaces().Contains(typeof(ISpecialArgumentClass)))
{
// Next line is a compilation error. How can I get a similar result?
GenericContainer<ISpecialArgumentClass> mySpecializedClassWithSpecialArgument = container as GenericContainer<ISpecialArgumentClass>;
mySpecializedClassWithSpecialArgument.t.ISpecialArgumentClassMethod();
}
}
}
}
}
}
注意:您可以在此处分叉和编辑代码。
你得到编译错误,因为ISpecialArgumentClass
不是类型 IArgumentClass
,但你的GenericClass
恰恰需要这个。
为了解决这个问题,你可以引入一个空接口,作为两个参数类的基础:
首先,像这样修改接口声明:
public interface IArgumentClassBase
{
}
public interface IArgumentClass : IArgumentClassBase
{
String GetNormalString();
}
public interface ISpecialArgumentClass : IArgumentClassBase
{
String GetSpecialString();
}
。然后修改泛型类声明,如下所示:
public class GenericClass<T> : IContainerClass
where T : IArgumentClassBase, new()
然后你的代码的其余部分应该可以工作了...
一个非常简单的解决方案是将其转换为动态 - 你知道它有一个t
字段,所以这样做应该是安全的。
if (typeArgument.GetInterfaces().Contains(typeof(ISpecialArgumentClass)))
{
dynamic mySpecializedClassWithSpecialArgument =
mySpecializedClass as dynamic;
ISpecialArgumentClass specialArgumentClass = mySpecializedClassWithSpecialArgument.t;
Console.WriteLine(specialArgumentClass.GetSpecialString());
}
注意
我试图在 ideone 中编辑它,但它无法编译。我怀疑它针对的是旧版本的 .NET - 动态是在 .NET 4 (VS 2010) 中引入的。但是,我已经在 2013 年测试了代码并且它可以工作。