简体   繁体   English

使用泛型进行反射

[英]Reflection using generics

I'd like to return the properties of a series of DbSet objects I have saved to a class using reflection, but in order to access this data in a single method I'd need to pass a variable as an accessor to return the properties of that object. 我想返回使用反射保存到类中的一系列DbSet对象的属性,但是为了以单个方法访问此数据,我需要传递一个变量作为访问器以返回的属性。该对象。

Currently I've managed to return the properties of all of the DbSet objects, but the code looks very DRY. 目前,我设法返回了所有DbSet对象的属性,但是代码看起来很干。

public DbSet<Foo> Foo {get;set;}
public DbSet<Bar> Bar {get;set;}

public List<string> GetPropertiesFoo()
{
    DbContext client = new DbContext();
    return client.Foo.GetType().GetProperties().Select(e => e.Name).ToList();
}
public List<string> GetPropertiesBar()
{
    DbContext client = new DbContext();
    return client.Bar.GetType().GetProperties().Select(e => e.Name).ToList();
}

My intention is to refactor this so that it accepts a DbSet name as an argument and returns a single list of properties, rather than a list of all properties. 我的意图是重构它,以便它接受DbSet名称作为参数并返回单个属性列表,而不是所有属性列表。

You are looking for something like this to do it all in one hit. 您正在寻找这样的东西来一次完成所有操作。 Note this code is quite verbose so that each step can be explained: 请注意,此代码非常冗长,因此可以解释每个步骤:

// Make the method generic so we can use it on any context
public List<string> GetProperties<TContext>(string dbSetName = "")
    where TContext : DbContext // Make sure we have a Dbcontext
{
    var propertyNames = typeof(TContext)

        // Get all properties of context
        .GetProperties() 

         // Filter out so we only have DbSet<> types
        .Where(pi => pi.PropertyType.IsGenericType &&
                     typeof(DbSet<>).IsAssignableFrom(pi.PropertyType.GetGenericTypeDefinition()))

        // If a DbSet name has been specified, filter it out
        .Where(pi => string.IsNullOrEmpty(dbSetName) || pi.Name == dbSetName)

        // Get the generic type e.g. Foo
        .Select(pi => pi.PropertyType.GetGenericArguments()[0])

        // Get the individual properties of the entity types
        .Select(t => t.GetProperties())

        // Get all of the property names
        .SelectMany(x => x.Select(pi => pi.Name)); 

    return propertyNames.ToList();
}

And use it like this: 并像这样使用它:

// All properties for all sets
var allProperties = GetProperties<MyContext>();

// Only properties for the Foo set
var fooProperties = GetProperties<MyContext>("Foo");

I think you might be after something like this 我想你可能会喜欢这样的事情

public List<string> GetProperties(string model)
{
   var property = 
      this.GetType()
      .GetProperties()
      .Where(p=>p.Name == model)
      .FirstOrDefault();

   if(property == null) return IEnumerable.Empty<string>().ToList();
   return property
      .PropertyType
      .GetGenericArguments()[0]
      .GetProperties()
      .Select(p=>p.Name)
      .ToList();
}
public List<Foo> GetFooFromBar(string bar)
{
     return = typeof(FooContext)//a list of DbSets (DbSet<Foo>, DbSet<Bar>)
    .GetProperties()
    .Where(e => e.Name == bar)//Filter based on the name of DbSet entered
    .GetType()//Get Type of the object returned (the DbSet with a matching name)
    .GetGenericArguments()[0]//Get the first item in the array of PropertyInfo
    .GetProperties()//Get a list of the properties of the DbSet within the Context
    .ToList();
    return bar;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM