如果T未知,如何创建Func <t,bool =“”>

时间:2016-10-13 21:05:23

标签: c# lambda

我有一个对象,他的实例是在运行时创建的,如下所示:

MemoryStream

我需要通过Id找到一个对象,为此我构建了以下方法:

var type = GetTypeFromAssembly(typeName, fullNameSpaceType);
        var instanceOfMyType = Activator.CreateInstance(type);
        ReadObject(instanceOfMyType.GetType().GetProperties(), instanceOfMyType, fullNameSpaceType);
        return instanceOfMyType;

但抛出一个未处理的异常,说:

  

实例属性&#39; Id&#39;未定义类型&#39; System.Object&#39;

那么,我如何用T构建一个Func,其中T在运行时被设置?像这样:

var parameter = Expression.Parameter(typeof(object));

        var condition =
            Expression.Lambda<Func<object, bool>>(
                Expression.Equal(
                    Expression.Property(parameter, theEntity.GetType().GetProperty("Id").Name),
                    Expression.Constant(id, typeof(TKey))
                    ), parameter
                ).Compile();

更新[无实体框架的解决方案]

我做了以下:

var parameter = Expression.Parameter(typeof(MyObjectReflectionRuntimeType>));

        var condition =
            Expression.Lambda<Func<MyObjectReflectionRuntimeType, bool>>(
                Expression.Equal(
                    Expression.Property(parameter, theEntity.GetType().GetProperty("Id").Name),
                    Expression.Constant(id, typeof(TKey))
                    ), parameter
                ).Compile();

但它在实体框架上崩溃,因为 public interface IBaseObject<T> { T Id { get; set; } } public class AnyClass : IBaseObject<Guid> { public Guid Id { get; set; } } var parameter = Expression.Parameter(typeof(IBaseObject<Guid>)); var id = Guid.NewGuid(); var theEntity = new AnyClass(); var theList = new List<AnyClass> { new AnyClass { Id = Guid.NewGuid() }, new AnyClass { Id = Guid.NewGuid() }, new AnyClass { Id = id }, new AnyClass { Id = Guid.NewGuid() } }; var condition = Expression.Lambda<Func<IBaseObject<Guid>, bool>>( Expression.Equal( Expression.Property(parameter, theEntity.GetType().GetProperty("Id").Name), Expression.Constant(id, typeof(Guid)) ), parameter ).Compile(); var theMetaData = theList.Where(condition).FirstOrDefault(); 不是上下文的一部分:( ...

[更新二]

我找到了这样的解决方案但不是最优的(感谢@Serge Semenov):

IBaseObject<T>

我说这不是最好的方式,因为我不想使用 var parameter = Expression.Parameter(typeof(object)); var entity = Expression.Convert(parameter, theEntity.GetType()); var condition = Expression.Lambda<Func<object, bool>>( Expression.Equal( Expression.Property(entity, theEntity.GetType().GetProperty("Id").Name), Expression.Constant(id, typeof(TKey)) ), parameter ).Compile(); var theObject = await _unitOfWork.Set(theEntity.GetType()).ToListAsync(); return theObject.FirstOrDefault(condition); 我想使用:await _unitOfWork.Set(theEntity.GetType()).ToListAsync();但它不起作用......

任何想法??

1 个答案:

答案 0 :(得分:0)

您将object传递给Func<>,但访问其他类型定义的Id媒体资源。

最简单的解决方法是将object转换为类型T,然后访问其属性,就像在C#((T)obj).Id中一样:

var parameter = Expression.Parameter(typeof(object));
var entity = Expression.Convert(parameter, theEntity.GetType());
...
Expression.Property(entity, theEntity.GetType().GetProperty("Id").Name),
...