我有一个通用方法,我给它任何类型T的对象和一个属性列表,它将返回该对象,该对象具有由列表定义的属性设置为空
这是我的代码
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; }
}
我的问题在代码上方的注释中。我不喜欢字符串类型[],我想要打字稿中的 T键之类的东西
我正在使用具有最新.NET核心的最新C#版本
答案 0 :(得分:1)
释义一下:
///我想要Visual Studio中的自动完成列表来告诉程序员T的哪些属性可用
问题是类型T
可能是任何内容。您必须能够在完全不同的程序集中使用此代码,Visual Studio和编译器都不会在编译时知道您的T
。
我不会说这是不可能的。 Visual Studio具有非常好的可扩展性,尤其是现在我们有了Roslyn。但这就是您要做的:使用Roslyn分析代码并提供完成列表的自定义Visual Studio扩展。这不是内置在平台中。
答案 1 :(得分:0)
尽管以下答案可以满足您的要求,但实际上没有意义,因为它只是不必要的。如果必须指定该属性,则最好直接设置它。
这里可能与您近在咫尺。我不相信您可以使用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; }
}
输出:
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