我有一系列类型为IRegistration []
的Castle windsor注册组件在这种情况下ComponentRegistration<T> : IRegistration
对于我的数组中的每个元素,
如果它可以上传到ComponentRegistration&lt;&gt;我想把它重新转回ComponentRegistration<T>
并进行处理。我到底该怎么做?
我到目前为止
foreach (var r in registrations) {
if(typeof(ComponentRegistration<>).IsAssignableFrom(r.GetType())) {
var cr = CAST r SOMEHOW
DoStuff(cr);
}
答案 0 :(得分:3)
当然,如果你有一个IRegistration[]
,那么你就是向下转播而不是向上转播。
但是,为了解决您的问题,DoStuff()
看起来像什么?是否需要知道ComponentRegistration<T>
的类型参数?如果没有,您可能最好创建一个非泛型基类:
public abstract class ComponentRegistration : IRegistration
{
// Anything in the original API which didn't use T
}
public class ComponentRegistration<T> : ComponentRegistration
{
// The bits which need T
}
然后你可以写:
foreach (var r in registrations)
{
ComponentRegistration cr = r as ComponentRegistration;
if (cr != null)
{
DoStuff(cr);
}
}
如果您确实需要DoStuff
来使用通用信息,则必须使用反射来获取适当的类型并调用它。尽可能避免:)
using System;
using System.Reflection;
class Test
{
static void Main()
{
Delegate[] delegates = new Delegate[]
{
(Action<int>) (x => Console.WriteLine("int={0}", x)),
(Action<string>) (x => Console.WriteLine("string={0}", x)),
(Func<int, int>) (x => x + 1)
};
MethodInfo genericPerformAction = typeof(Test).GetMethod
("PerformAction");
foreach (Delegate del in delegates)
{
Type t = DiscoverTypeArgument(del, typeof(Action<>));
if (t == null)
{
// Wrong type (e.g. the Func in the array)
continue;
}
MethodInfo concreteMethod = genericPerformAction.MakeGenericMethod
(new[] { t } );
concreteMethod.Invoke(null, new object[] { del });
}
}
public static void PerformAction<T>(Action<T> action)
{
Console.WriteLine("Performing action with type {0}", typeof(T).Name);
action(default(T));
}
/// <summary>
/// Discovers the type argument for an object based on a generic
/// class which may be somewhere in its class hierarchy. The generic
/// type must have exactly one type parameter.
/// </summary>
/// <returns>
/// The type argument, or null if the object wasn't in
/// the right hierarchy.
/// </returns>
static Type DiscoverTypeArgument(object o, Type genericType)
{
if (o == null || genericType == null)
{
throw new ArgumentNullException();
}
if (genericType.IsInterface ||
!genericType.IsGenericTypeDefinition ||
genericType.GetGenericArguments().Length != 1)
{
throw new ArgumentException("Bad type");
}
Type objectType = o.GetType();
while (objectType != null)
{
if (objectType.IsGenericType &&
objectType.GetGenericTypeDefinition() == genericType)
{
return objectType.GetGenericArguments()[0];
}
objectType = objectType.BaseType;
}
return null;
}
}
编辑:请注意如果你处于所有成员来自相关类的情况,如果你'使用C#4,您可以使用动态绑定:
using System;
using System.Reflection;
class Test
{
static void Main()
{
Delegate[] delegates = new Delegate[]
{
(Action<int>) (x => Console.WriteLine("int={0}", x)),
(Action<string>) (x => Console.WriteLine("string={0}", x)),
(Action<long>) (x => Console.WriteLine("long={0}", x)),
};
foreach (dynamic del in delegates)
{
// Yay for dynamic binding
PerformAction(del);
}
}
public static void PerformAction<T>(Action<T> action)
{
Console.WriteLine("Performing action with type {0}", typeof(T).Name);
action(default(T));
}
}
不幸的是,我不知道有任何方法可以测试它是否能够成功地绑定到方法而不仅仅是尝试它并捕获相关的异常(这将是严峻的)。也许埃里克能够告诉我们:)
答案 1 :(得分:1)
不幸的是,如果没有
,你就无法做到这一点编辑反思黑客
基本上,您需要使用反射来获取运行时类型。检查类型以获取ComponentRegistration中的通用T.然后使用该T实例化方法DoStuff的实例,并将对象作为参数传递。
答案 2 :(得分:0)
如果您尝试向上转换的类是非泛型的,那么您可以通过强制转换对象来解决此问题:
abstract class A<T> where T : A<T>
{
T derived;
void foo()
{
B b1 = (B)derived; // Error CS0030: 'Cannot convert type 'T' to 'B'
B b2 = (B)(Object)derived; // Ok
}
};
class B : A<B> { };