【问题标题】:How do I set return type from method with an Expression<Func<TModel, TProperty>>如何使用 Expression<Func<TModel, TProperty>> 从方法设置返回类型
【发布时间】:2020-12-02 12:38:18
【问题描述】:

我想调用一个带有类似签名的方法

string fullname = UserBuilder.DefaultProperty(e => e.Fullname)

我创建了一个构建器类,并希望从提供的默认值中返回默认属性

public class BuilderGeneric<TModel>
{
    private readonly TModel _defaultModel;

    public BuilderGeneric(TModel defaultModel)
    {
        _defaultModel = defaultModel;
    }

    public object DefaultProperty<TProperty>([NotNull] Expression<Func<TModel, TProperty>> propertyExpression)
    {
        // Reflection here to get the property
        // ...
        var propertyType = myPropInfo.PropertyType;
        var propertyValue = myPropInfo.GetValue(_defaultModel);

        return propertyValue;
    }
}

我怎样才能使它不返回一个对象,而是在该示例中返回 e =&gt; e.Fullname) 中的属性类型,它将是一个字符串

【问题讨论】:

  • 这个方法的工作原理还不是很清楚,能否详细说明一下表达式与返回类型有什么关系?
  • 你只是在追public TProperty DefaultProperty&lt;TProperty&gt;(...)吗?你当然需要返回(TProperty)propertyValue
  • 另请注意,您不一定需要“在此处进行反射以获取属性”-propertyExpression.Compile()(_defaultModel) 会这样做。你甚至不需要为此使用表达式——public TProperty DefaultProperty&lt;TProperty&gt;(Func&lt;TModel, TProperty&gt; propertyGetter) =&gt; propertyGetter(_defaultModel);
  • :'( 我不知道为什么我会从这个问题中得到否定的答案。我试图让它简短易读,而不是太担心我试图做什么来获得属性值但专注于返回正确的类型
  • 您可能投了反对票,因为您从 DefaultProperty 中删除了重要的内容,并且只留下了评论。不要那样做——给我们代码,我们可以运行它并展示你的错误。我不得不做一些猜测来弄清楚你可能会问什么。你得到了minimal reproducible example 的“最小”部分,但没有得到“可重现”部分

标签: c# .net generics expression func


【解决方案1】:

感谢@canton7

我正在尝试创建一个通用构建器类,我将其与单元测试一起包含在下面。

我希望这可以帮助任何尝试做类似事情的人。

public class BuilderGeneric<TModel>
    where TModel : class
{
    private readonly TModel _defaultModel;

    private TModel BuilderEntity { get; }

    public BuilderGeneric(TModel defaultModel)
    {
        _defaultModel = defaultModel;
        BuilderEntity = (TModel)Activator.CreateInstance(typeof(TModel));
    }

    public TProperty DefaultProperty<TProperty>(Func<TModel, TProperty> property)
    {
        return property(_defaultModel);
    }

    public BuilderGeneric<TModel> With<TProperty>(Expression<Func<TModel, TProperty>> property, TProperty value)
    {
        var memberExpression = (MemberExpression)property.Body;
        var propertyInfo = (PropertyInfo)memberExpression.Member;

        propertyInfo.SetValue(BuilderEntity, value);

        return this;
    }

    public TModel Build()
    {
        return BuilderEntity;
    }
}

public class UserBuilder : BuilderGeneric<UserProfile>
{
    public UserBuilder()
        : base(new UserProfile()
        {
            FullName = "Ian Bowyer",
            EmailAddress = "Email@Email.com",
            MyGuid = new Guid("12345678-1234-1234-1234-123456789012")
        })
    {
    }
}

public class UserProfile
{
    public string FullName { get; set; }

    public string EmailAddress { get; set; }

    public Guid MyGuid { get; set; }
}

public class TestGenericBuilder
{
    [Test]
    public void TestTheDefaultPropertyReturns()
    {
        // Assert
        var userBuilder = new UserBuilder()
            .With(e => e.FullName, "Bobby Tables")
            .With(e => e.MyGuid, new Guid("85EC85CF-2892-40B8-BF63-0C621F78BE27"));

        var user = userBuilder.Build();

        // Act
        var defaultFullname = userBuilder.DefaultProperty(e => e.FullName);

        // Assert
        defaultFullname.Should().Be("Ian Bowyer");
        user.FullName.Should().Be("Bobby Tables");
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多