如何设置值属性选择器Expression <Func <T,TResult >>

Emi*_*tes 25 c# linq expression-trees

我需要使用模式工厂的想法将我的Person类实体中的实体属性Address与我的FactoryEntities类中的表达式linq相关联,看看这就是我拥有的和我想做的事情:

Address address = new Address();
address.Country = "Chile";
address.City = "Santiago";
address.ZipCode = "43532";
//Factory instance creation object
//This is idea
Person person = new FactoryEntity<Person>().AssociateWithEntity(p=>p.Address, address);

public class Person: Entity
{
    public string Name{ get; set; }
    public string LastName{ get; set; }
    public Address Address{ get; set; }
}

public class Address: Entity
{
    public string Country{ get; set; }
    public string City{ get; set; }
    public string ZipCode{ get; set; }
}

public class FactoryEntity<TEntity> where TEntity : Entity
{
    public void AssociateWithEntity<TProperty>(Expression<Func<TEntity, TProperty>> entityExpression, TProperty newValueEntity) where TProperty : Entity
    {
        if (instanceEntity == null || instanceEntity.IsTransient())
            throw new ArgumentNullException();

        /*TODO: Logic the association and validation 
        How set the newValueEntity into the property of entityExpression (x=>x.Direccion = direccion*/
    }
}
Run Code Online (Sandbox Code Playgroud)

sma*_*man 28

这有效:

以下帮助器方法将getter表达式转换为setter委托.如果你想返回一个Expression<Action<T,TProperty>>而不是一个Action<T,TProperty>,只是不要Compile()在最后调用该方法.

注:该代码是由伊恩·默瑟的博客:http://blog.abodit.com/2011/09/convert-a-property-getter-to-a-setter/

    /// <summary>
    /// Convert a lambda expression for a getter into a setter
    /// </summary>
    public static Action<T, TProperty> GetSetter<T, TProperty>(Expression<Func<T, TProperty>> expression)
    {
        var memberExpression = (MemberExpression)expression.Body;
        var property = (PropertyInfo)memberExpression.Member;
        var setMethod = property.GetSetMethod();

        var parameterT = Expression.Parameter(typeof(T), "x");
        var parameterTProperty = Expression.Parameter(typeof(TProperty), "y");

        var newExpression =
            Expression.Lambda<Action<T, TProperty>>(
                Expression.Call(parameterT, setMethod, parameterTProperty),
                parameterT,
                parameterTProperty
            );

        return newExpression.Compile();
    }
Run Code Online (Sandbox Code Playgroud)

  • @hbob ,类似于:`GetSetter( (string example) =&gt; example.Length )` (2认同)

svi*_*ick 6

您可以像这样设置属性:

public void AssociateWithEntity<TProperty>(
    Expression<Func<TEntity, TProperty>> entityExpression,
    TProperty newValueEntity)
    where TProperty : Entity
{
    if (instanceEntity == null)
        throw new ArgumentNullException();

    var memberExpression = (MemberExpression)entityExpression.Body;
    var property = (PropertyInfo)memberExpression.Member;

    property.SetValue(instanceEntity, newValueEntity, null);
}
Run Code Online (Sandbox Code Playgroud)

这仅适用于属性,而不适用于字段,尽管添加对字段的支持应该很容易.

但是你获得这个人的代码是行不通的.如果你想保留void返回类型AssociateWithEntity(),你可以这样做:

var factory = new FactoryEntity<Person>();
factory.AssociateWithEntity(p => p.Address, address);
Person person = factory.InstanceEntity;
Run Code Online (Sandbox Code Playgroud)

另一种选择是流畅的界面:

Person person = new FactoryEntity<Person>()
    .AssociateWithEntity(p => p.Address, address)
    .InstanceEntity;
Run Code Online (Sandbox Code Playgroud)