簡體   English   中英

具有參數是類的屬性的類型

[英]having parameters be the type of the properties of a class

我有一個通用方法,我給它任何類型T的對象和一個屬性列表,它將返回該對象,該對象具有由列表定義的屬性設置為null

這是我的代碼

class Program
{
    static void Main(string[] args)
    {
        var orderDto = new OrderDto();
        orderDto.Nominal = "1";
        orderDto.OrderId = "2";
        orderDto.Type = "3";

        var clean = FieldCleaner.Clean(orderDto, "OrderId");
    }
}

public class FieldCleaner
{
    public static T Clean<T>(T dto, params string[] properties) // I want in compilation time, have autocompletion that tell user the value of properties can only be a property name of the type T
    {
        var propertyInfos = dto.GetType().GetProperties();
        foreach (var propertyInfo in propertyInfos)
        {
            foreach (var property in properties)
            {
                if (propertyInfo.Name == property)
                {
                    propertyInfo.SetValue(dto, null);
                }
            }
        }

        return dto;
    }
}

public class OrderDto
{
    public string OrderId { get; set; }
    public string Nominal { get; set; }
    public string Type { get; set; }
}

我的問題在代碼上方的注釋中。 我不喜歡string []類型,我想要像打字稿中的keyof T這樣的東西

我使用最新的C#版本和最新的.NET核心

釋義一下:

//我想要Visual Studio中的自動完成列表來告訴程序員T的哪些屬性可用

問題是類型T可以是任何東西 您必須能夠在完全不同的程序集中使用此代碼,而Visual Studio和編譯器都不會在編譯時知道您的T

我不會說這是不可能的。 Visual Studio是非常可擴展的,尤其是現在有了Roslyn 但這就是您要做的:使用Roslyn分析代碼並提供完成列表的自定義Visual Studio擴展。 這不是內置在平台中。

盡管以下答案可以滿足您的要求,但實際上沒有意義,因為它只是不必要的。 如果必須指定該屬性,則最好直接設置它。

這可能是您所能接近的。 我不相信您可以使用params因為這將要求所有TProp都為同一類型。

在Visual Studio中,當您到達句號時,您將獲得智能感知:

在此處輸入圖片說明

using System;
using System.Linq.Expressions;
using System.Reflection;

public class Program
{
    public static void Main()
    {
        var orderDto = new OrderDto
        {
            Id = 1,
            Name = "Name",
            CreatedOn = DateTime.UtcNow,
            CompletedOn = DateTime.UtcNow.AddMinutes(30),
            Misc = Guid.NewGuid()
        };

        Console.WriteLine($"{orderDto.Id} {orderDto.Name} {orderDto.CreatedOn} {orderDto.CompletedOn} {orderDto.Misc}");

        orderDto.DefaultFor(x => x.Id, x => x.Name, x => x.CreatedOn, x => x.CompletedOn);

        Console.WriteLine($"{orderDto.Id} {orderDto.Name} {orderDto.CreatedOn} {orderDto.CompletedOn} {orderDto.Misc}");
    }
}

public static class ObjectExtensions
{
    public static void DefaultFor<TObject, TProp1, TProp2, TProp3, TProp4>(this TObject instance, 
        Expression<Func<TObject, TProp1>> selector1, 
        Expression<Func<TObject, TProp2>> selector2,
        Expression<Func<TObject, TProp3>> selector3,
        Expression<Func<TObject, TProp4>> selector4)
        where TObject : class
    {
        DefaultFor(instance, selector1, selector2, selector3);
        DefaultFor(instance, selector4);
    }

    public static void DefaultFor<TObject, TProp1, TProp2, TProp3>(this TObject instance, 
        Expression<Func<TObject, TProp1>> selector1, 
        Expression<Func<TObject, TProp2>> selector2,
        Expression<Func<TObject, TProp3>> selector3)
        where TObject : class
    {
        DefaultFor(instance, selector1, selector2);
        DefaultFor(instance, selector3);
    }

    public static void DefaultFor<TObject, TProp1, TProp2>(this TObject instance, 
        Expression<Func<TObject, TProp1>> selector1, 
        Expression<Func<TObject, TProp2>> selector2)
        where TObject : class
    {
        DefaultFor(instance, selector1);
        DefaultFor(instance, selector2);
    }

    public static void DefaultFor<TObject, TProp>(this TObject instance, Expression<Func<TObject, TProp>> selector)
        where TObject : class
    {
        if (instance == null)
            throw new ArgumentNullException();

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

        property.SetValue(instance, default(TProp));
    }
}

public class OrderDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedOn { get; set; }
    public DateTime? CompletedOn { get; set; }
    public Guid Misc { get; set; }
}

DotNetFiddle示例

輸出:

1名稱3/29/2019 5:14:06 AM 3/29/2019 5:44:06 AM 3800be41-7fe1-42da-ada5-4fe33ac04a84

0 1/1/0001 12:00:00 AM 3800be41-7fe1-42da-ada5-4fe33ac04a84

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM