[英]C# Access to a generic class member whose type is a generic argument type, only via an interface
我有一個泛型類,它擁有一個類型為參數類型的成員。
我希望只能通過其實現的接口之一訪問此成員。
我只想通過這個接口訪問成員,而不是枚舉它可能的所有具體類型的原因是因為有很多這些類型。
具體來說,我想在該代碼中找到等效的第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年對代碼進行了測試,但它確實有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.