我很确定我错过了某些限制或警告,但这就是我的情况。假设我有一个类想要代理它,例如以下内容:
public class MyList : MarshalByRefObject, IList<string>
{
private List<string> innerList;
public MyList(IEnumerable<string> stringList)
{
this.innerList = new List<string>(stringList);
}
// IList<string> implementation omitted for brevity.
// For the sake of this exercise, assume each method
// implementation merely passes through to the associated
// method on the innerList member variable.
}
我想为那个类创建一个代理,这样我就可以拦截方法调用并对底层对象执行一些处理。这是我的实现:
public class MyListProxy : RealProxy
{
private MyList actualList;
private MyListProxy(Type typeToProxy, IEnumerable<string> stringList)
: base(typeToProxy)
{
this.actualList = new MyList(stringList);
}
public static object CreateProxy(IEnumerable<string> stringList)
{
MyListProxy listProxy = new MyListProxy(typeof(MyList), stringList);
object foo = listProxy.GetTransparentProxy();
return foo;
}
public override IMessage Invoke(IMessage msg)
{
IMethodCallMessage callMsg = msg as IMethodCallMessage;
MethodInfo proxiedMethod = callMsg.MethodBase as MethodInfo;
return new ReturnMessage(proxiedMethod.Invoke(actualList, callMsg.Args), null, 0, callMsg.LogicalCallContext, callMsg);
}
}
最后,我有一个消费代理类的类,并通过反射设置MyList
成员的值。
public class ListConsumer
{
public MyList MyList { get; protected set; }
public ListConsumer()
{
object listProxy = MyListProxy.CreateProxy(new List<string>() { "foo", "bar", "baz", "qux" });
PropertyInfo myListPropInfo = this.GetType().GetProperty("MyList");
myListPropInfo.SetValue(this, listProxy);
}
}
现在,如果我尝试使用反射来访问代理对象,就会遇到问题。以下是一个例子:
class Program
{
static void Main(string[] args)
{
ListConsumer listConsumer = new ListConsumer();
// These calls merely illustrate that the property can be
// properly accessed and methods called through the created
// proxy without issue.
Console.WriteLine("List contains {0} items", listConsumer.MyList.Count);
Console.WriteLine("List contents:");
foreach(string stringValue in listConsumer.MyList)
{
Console.WriteLine(stringValue);
}
Type listType = listConsumer.MyList.GetType();
foreach (Type interfaceType in listType.GetInterfaces())
{
if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(ICollection<>))
{
// Attempting to get the value of the Count property via
// reflection throws an exception.
Console.WriteLine("Checking interface {0}", interfaceType.Name);
System.Reflection.PropertyInfo propInfo = interfaceType.GetProperty("Count");
int count = (int)propInfo.GetValue(listConsumer.MyList, null);
}
else
{
Console.WriteLine("Skipping interface {0}", interfaceType.Name);
}
}
Console.ReadLine();
}
}
尝试通过反射调用Count属性上的GetValue方法会引发以下异常:当尝试获取Count属性的值时,显然框架会向下调用System.Runtime.InteropServices.WindowsRuntime.IVector来调用get_Size方法。我不理解为什么基础代理对象(实际列表)上的此调用会失败,导致这种情况发生。如果我没有使用对象的代理,通过反射获取属性值是可以正常工作的。我做错了什么?我能否完成我正在尝试的操作?编辑: 此问题已在Microsoft Connect站点上开放了漏洞。System.Reflection.TargetException 异常在 mscorlib.dll 中发生,但未在用户代码中处理
额外信息:对象不符合目标类型。
Assert.Count
方法对于某些集合进行了处理。如果集合对象是代理,则调用Assert.Count
会抛出异常。 - JimEvansMyListProxy.CreateProxy
成为泛型函数,以便返回实际类型而非类型对象?对于测试,请问:如果将主函数中的调用interfaceType.GetProperty("Count")
更改为((MyList)interfaceType).GetProperty("Count")
,那么对Count
的调用是否有效? - keenthinker