属性类型作为通用参数 [英] Property Type as Generic parameter

查看:118
本文介绍了属性类型作为通用参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图弄清楚如何才能使泛型调用为类型创建一个变量。在下面的调用中,它采用类型DAL.Account并且工作正常。

  var tst = ctx.GetTable< DAL。帐户>()。其中​​(t => t.Sbank ==000134); 

我想改变它以便我可以传递一个变量来代替DAL.Account 。像这样的东西,但我知道这是行不通的,因为你不能将属性作为Type来传递。

  ctx.GetTable< Criteria.EntityType>()。其中​​(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag),Criteria.StateBag.Values.ToArray())

下面是我认为解释我想要做的事情的shell代码段。泛型不是我的强项,所以我正在寻求一些帮助。无论如何,我可以做到这一点?

  //存储一个Type,表示Object是一个Criteria标准。 
public class AccountCriteria:IGeneratedCriteria
{
...

public Type EntityType
{
get {return typeof(DAL.Account) ;}
}
}

//我在DataContext中添加了一个名为GetTable的函数
//然后在Console中用它作为示例应用程序来测试其功能。
public class ADRPDataContext:NHibernateDataContext
{
...

public CodeSmith.Data.NHibernate.ITable< T> GetTable< T>()其中T:EntityBase
{
var tb = new CodeSmith.Data.NHibernate.Table< T>(this);
返回tb;



//使用DataContext.GetTable的控制台应用程序
class程序
{
static void Main(string [] args )
{
using(var ctx = new ADRPDataContext())
{
var tst = ctx.GetTable< DAL.Account>()其中(t => t .Sbank ==000134);
}
}
}

//使用Critera的EntityType属性生成数据的ExistsCommand类。
public class ExistsCommand
{
private IGeneratedCriteria Criteria {get;组; }
$ b保护覆盖无效DataPortal_Execute()
{
使用(var ctx = new DC.ADRPDataContext())
{
//这是我的第一次尝试但不起作用,因为您无法为类型传递属性。
//但是我可以弄清楚如何编写它以便它能够工作。
Result = ctx.GetTable< Criteria.EntityType>()。其中​​(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag),Criteria.StateBag.Values.ToArray())。Count()> 0;




解决方案

您正在寻找实例化一个泛型类型。一些信息可以在这里找到



这是一个简单的例子,演示如何实例化一个容量为3的List。下面是一个方法,您可以在不知道类型时调用它来创建泛型:

  public static Object CreateGenericListOfType(Type typeGenericWillBe)
{
//替代以下内容:
// List<串GT; myList = new List< String>(3);


//为泛型的构造函数构建参数(显然,如果每种潜在类型都有不同的构造函数,此代码将不起作用)
object [] constructorArgs = new Object [ 1];
constructorArgs [0] = 3;


//实例化泛型。与调用上面的一行示例(注释掉)相同。结果在列表< String>带有3个列表项
类型genericListType = typeof(List<>);
类型[] typeArgs = {typeGenericWillBe};
类型myNewGeneric = genericListType.MakeGenericType(typeArgs);
对象GenericOfType = Activator.CreateInstance(myNewGeneric,constructorArgs);


返回GenericOfType;

$ / code>

下面是一些示例代码,它们将向您展示示例方法的作用:

 列表< String> Strings =(List< String>)InstantiateGenericTypeWithReflection.CreateGenericListOfType(typeof(String)); 

//演示该对象实际上是一个List< String>我们可以像使用linq扩展一样做东西(对linq没有太大的用处,但是可以作为例子)
Strings.Add(frist);
Strings.Add(2nd);
Strings.Add(tird);
Console.WriteLine(item index 2 value:+ Strings.Where(strings => strings ==2)。First());

在你的例子中,替换你的 GetTable< Criteria.EntityType> / code>与 CreateGenericTableOfType(Criteria.EntityType)。这将返回一个通用的任何类型的通用表。您当然需要正确实现该方法(处理构造函数参数,将List更改为Table等)。

I'm trying to figure out how I can make a Generics call take a variable for the Type. In the call below it take a type "DAL.Account" and works fine.

var tst = ctx.GetTable<DAL.Account>().Where(t => t.Sbank == "000134");

I want to change that so that I can pass a variable in place of the "DAL.Account". Something like this but I know that won't work as you can't pass property as a Type.

ctx.GetTable<Criteria.EntityType>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray())

Below is the shell pieces of code I think explains what I'm trying to do. Generics is not my strong suit so I'm looking for some help. Is there anyway that I can make this happen?

//Stores a "Type" that indicates what Object is a Criteria for.
public class AccountCriteria : IGeneratedCriteria
{
    ...

    public Type EntityType
    {
        get {return typeof(DAL.Account);}
    }
}

//I have added a function to the DataContext called "GetTable"
// And then used it as an example in a Console App to test its functionality.
public class ADRPDataContext : NHibernateDataContext
{
    ...

    public CodeSmith.Data.NHibernate.ITable<T> GetTable<T>() where T : EntityBase
    {
         var tb = new CodeSmith.Data.NHibernate.Table<T>(this);
         return tb;
    }
}

// console application that uses DataContext.GetTable
class Program
{
    static void Main(string[] args)
    {
        using (var ctx = new ADRPDataContext())
        {
            var tst = ctx.GetTable<DAL.Account>().Where(t => t.Sbank == "000134");
        }
    }
}

//ExistsCommand class that uses the EntityType property of the Critera to generate the data.
public class ExistsCommand
{
    private IGeneratedCriteria Criteria { get; set; }

    protected override void DataPortal_Execute()
    {
        using (var ctx = new DC.ADRPDataContext())
        {
            //This was my first attempt but doesn't work becuase you can't pass a property in for a Type.
            //But I can figure out how to write this so that it will work.
            Result = ctx.GetTable<Criteria.EntityType>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray()).Count() > 0;
        }
    }
}

解决方案

You are looking to instantiate a generic type. Some info can be found here

This is a simple example demonstrating how to instantiate a List with a capacity of 3. Here is a method that you can call to create a generic when you don't know the type:

public static Object CreateGenericListOfType(Type typeGenericWillBe)
    {
        //alternative to the followin:
        //List<String> myList = new List<String>(3);


        //build parameters for the generic's constructor (obviously this code wouldn't work if you had different constructors for each potential type)
        object[] constructorArgs = new Object[1];
        constructorArgs[0] = 3;


        //instantiate the generic.  Same as calling the one line example (commented out) above. Results in a List<String> with 3 list items
        Type genericListType = typeof(List<>);
        Type[] typeArgs = { typeGenericWillBe };
        Type myNewGeneric = genericListType.MakeGenericType(typeArgs);
        object GenericOfType = Activator.CreateInstance(myNewGeneric, constructorArgs);


        return GenericOfType;
    }

And here is some sample code that will show you the example method works:

List<String> Strings = (List<String>)InstantiateGenericTypeWithReflection.CreateGenericListOfType(typeof(String));

        //demonstrate the object is actually a List<String> and we can do stuff like use linq extensions (isn't a good use of linq but serves as example)
        Strings.Add("frist");
        Strings.Add("2nd");
        Strings.Add("tird");
        Console.WriteLine("item index 2 value: " + Strings.Where(strings => strings == "2").First());

In your example, replace your GetTable<Criteria.EntityType>() with CreateGenericTableOfType(Criteria.EntityType). This will return a generic table of whatever type you pass in. You will of course need to implement the method properly (handle constructor args, change List to Table etc).

这篇关于属性类型作为通用参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆