C# 如何使用反射调用DomainService.Load方法?
我正在尝试构建一个实用方法,该方法将使用反射来加载entitycollections。其思想是,使用该实用程序的程序员可以指定任何类型的实体,该方法将发现正确的EntityQuery,并加载他们所请求的上下文。因此,我已经从用户那里收集了实体类型和Where子句,现在我试图找出如何调用该方法。以下是我所拥有的:C# 如何使用反射调用DomainService.Load方法?,c#,silverlight,reflection,ria,C#,Silverlight,Reflection,Ria,我正在尝试构建一个实用方法,该方法将使用反射来加载entitycollections。其思想是,使用该实用程序的程序员可以指定任何类型的实体,该方法将发现正确的EntityQuery,并加载他们所请求的上下文。因此,我已经从用户那里收集了实体类型和Where子句,现在我试图找出如何调用该方法。以下是我所拥有的: public void Handle(LoadEntityQuery loadQuery, Action<LoadEntityQueryResult> reply) {
public void Handle(LoadEntityQuery loadQuery, Action<LoadEntityQueryResult> reply)
{
foreach (var entry in loadQuery.Entities)
{
Type entityType = entry.Key;
Type _contextType = EmployeeJobsContext.Instance.GetType();
MethodInfo _methodInfo = (from x in _contextType.GetMethods()
where x.ReturnType.BaseType == typeof(EntityQuery)
from y in x.ReturnType.GetGenericArguments()
where y == entityType
select x).FirstOrDefault();
if (_methodInfo != null)
{
var query = _methodInfo.Invoke(EmployeeJobsContext.Instance, null);
var _loadMethods = from x in _contextType.GetMethods()
where x.Name == "Load" &&
x.GetParameters().Length == 3
select x;
MethodInfo _loadMethod = null;
if (_loadMethods != null)
{
foreach (MethodInfo item in _loadMethods)
{
ParameterInfo[] _paramInfo = item.GetParameters();
if (_paramInfo[0].ParameterType.BaseType == typeof(EntityQuery) &&
_paramInfo[1].ParameterType.IsGenericType &&
_paramInfo[1].ParameterType.GetGenericArguments().Length == 1 &&
_paramInfo[1].ParameterType.GetGenericArguments()[0].BaseType == typeof(LoadOperation) &&
_paramInfo[2].ParameterType == typeof(object))
{
_loadMethod = item;
break;
}
}
}
MethodInfo _loadOpMethod = this.GetType().GetMethod("LoadOperationResult");
Delegate d = Delegate.CreateDelegate(typeof(LoadOpDel), _loadOpMethod);
if (_loadMethod != null)
{
object [] _params = new object[3];
_params[0] = query;
_params[1] = d;
_params[2] = null;
_loadMethod = _loadMethod.MakeGenericMethod(entityType);
_loadMethod.Invoke(_context, _params);
}
}
}
}
public delegate void LoadOpDel(LoadOperation loadOp);
public void LoadOperationResult (LoadOperation loadOp)
{
if (loadOp.HasError == true)
{
//reply(new LoadEntityQueryResult { Error = loadOp.Error.Message });
loadOp.MarkErrorAsHandled();
}
}
公共无效句柄(LoadEntityQuery loadQuery,操作回复)
{
foreach(loadQuery.Entities中的var条目)
{
Type entityType=entry.Key;
Type_contextType=EmployeeJobsContext.Instance.GetType();
MethodInfo _MethodInfo=(来自_contextType.GetMethods()中的x)
其中x.ReturnType.BaseType==typeof(EntityQuery)
从x.ReturnType.GetGenericArguments()中的y开始
其中y==entityType
选择x).FirstOrDefault();
如果(_methodInfo!=null)
{
var query=_methodInfo.Invoke(EmployeeJobsContext.Instance,null);
var_loadMethods=来自_contextType.GetMethods()中的x
其中x.Name==“加载”&&
x、 GetParameters()。长度==3
选择x;
MethodInfo\u loadMethod=null;
if(_loadMethods!=null)
{
foreach(加载方法中的MethodInfo项)
{
ParameterInfo[]_paramInfo=item.GetParameters();
if(_paramInfo[0].ParameterType.BaseType==typeof(EntityQuery)&&
_paramInfo[1]。ParameterType.IsGenericType&&
_paramInfo[1]。ParameterType.GetGenericArguments()。长度==1&&
_paramInfo[1]。ParameterType.GetGenericArguments()[0]。BaseType==typeof(LoadOperation)&&
_paramInfo[2]。ParameterType==typeof(对象))
{
_loadMethod=项目;
打破
}
}
}
MethodInfo_loadOpMethod=this.GetType().GetMethod(“LoadOperationResult”);
Delegate d=Delegate.CreateDelegate(typeof(LoadOpDel),\u loadOpMethod);
如果(_loadMethod!=null)
{
对象[]_参数=新对象[3];
_参数[0]=查询;
_参数[1]=d;
_params[2]=null;
_loadMethod=\u loadMethod.MakeGenericMethod(entityType);
_调用(_上下文,_参数);
}
}
}
}
公共委托无效LoadOpDel(LoadOperation loadOp);
公共无效LoadOperationResult(LoadOperation loadOp)
{
if(loadOp.HasError==true)
{
//回复(新的LoadEntityQueryResult{Error=loadOp.Error.Message});
loadOp.MarkErrorAsHandled();
}
}
foreach循环正在迭代Dictionary>>,其中键是实体类型,值是where子句。代码的第一部分是找到正确的EntityQuery方法并调用它以获得实际的查询。然后它会发现正确的加载重载(我知道,可能有更好的方法找到方法:)。这部分代码工作正常,我能够发现正确的EntityQuery和加载方法
对于LoadOperation,我想使用LoadOperationResult作为委托方法。但是,当我尝试运行此代码时,我收到一个异常,指出委托类型和方法类型签名不匹配。我非常确定我的签名是正确的,因为如果我直接调用Load并将函数名作为回调传递,那么这段代码将正常执行。我对反射式编程相当熟悉,但是在混合中使用泛型和动作回调在这一点上比我的水平略高。我不知道我做错了什么,有人能给我指点吗?我走远了吗?谢谢你的帮助!!
Jason在不了解您正在使用的类的任何其他信息的情况下,我无法真正测试我的解决方案,但是当我将委托创建从for循环中取出时,我可以让它工作。我已将目标方法更改为静态:
public static void LoadOperationResult(LoadOperation loadOp)
委托的创建没有任何问题
比方说,我在这方面不是特别有能力,但我认为您希望创建一次委托,并在需要时简单地重复使用它。为什么要一次又一次地创建它?即使
Action
和LoadOpDel
具有相同的签名,但不能在它们之间进行隐式转换。在C#中,类型强制有时会使这看起来不真实,但如果使用反射类型强制显然不会发挥其神奇作用。我发现我不需要使用反射来调用Load方法(不需要委托),而是通过创建基于实体类型的泛型方法来直接调用Load。以下是我为所有感兴趣的人提出的建议:
/// <summary>
/// The Action callback for the LoadEntityQuery handler. This callback is used to respond to the
/// LoadEntityQuery when all Load calls are complete. See the Handle method
/// </summary>
private Action<LoadEntityQueryResult> _reply = null;
/// <summary>
/// Accumulator used to determine when the last entity has been loaded
/// </summary>
private int EntityCount { get; set; }
/// <summary>
/// Collective error container for Errors from the LoadOperation. This is value is returned via
/// the _reply callback to the calling code.
/// </summary>
private List<Exception> Errors = null;
public void Handle(LoadEntityQuery loadQuery, Action<LoadEntityQueryResult> reply)
{
_reply = reply;
Errors = new List<Exception>();
EntityCount = loadQuery.Entities.Count();
MethodInfo _loadOpMethod = this.GetType().GetMethod("Load", BindingFlags.NonPublic | BindingFlags.Instance);
int _entityCount = loadQuery.Entities.Count();
foreach (var entry in loadQuery.Entities)
{
Type entityType = entry.Key;
Type _contextType = EmployeeJobsContext.Instance.GetType();
MethodInfo _methodInfo = (from x in _contextType.GetMethods()
where x.ReturnType.BaseType == typeof(EntityQuery)
from y in x.ReturnType.GetGenericArguments()
where y == entityType
select x).FirstOrDefault();
if (_methodInfo != null)
{
var query = _methodInfo.Invoke(EmployeeJobsContext.Instance, null);
MethodInfo _typedLoadOpMethod = _loadOpMethod.MakeGenericMethod(new Type[] { entityType });
_typedLoadOpMethod.Invoke(this, new[] { query, entry.Value});
}
}
}
private void Load<T>(EntityQuery<T> query, Expression<Func<T, bool>> where) where T: Entity
{
if (where != null)
query = query.Where(where);
EmployeeJobsContext.Instance.Load(query, (loadOp) =>
{
EntityCount--;
if (loadOp.HasError)
{
Errors.Add(loadOp.Error);
loadOp.MarkErrorAsHandled();
}
if (EntityCount == 0)
_reply(new LoadEntityQueryResult { ErrorList = Errors });
}, null);
}
//
///LoadEntityQuery处理程序的操作回调。此回调用于响应
///所有加载调用完成时的LoadEntityQuery。参见Handle方法
///
私人行动_reply=null;
///
///累加器用于确定加载最后一个实体的时间
///
private int EntityCount{get;set;}
///
///LoadOperation错误的集合错误容器。这是通过返回的值
///对调用代码的_reply回调。
///
私有列表错误=null;
公共无效句柄(LoadEntityQuery loadQuery,操作回复)
{
_答复=答复;
错误=新列表();
EntityCount=loadQuery.Entities.Count();
MethodInfo _loadOpMethod=this.GetType().GetMethod(“加载”,BindingFlags.NonPublic |绑定