2010-11-19 33 views
2

因此,我正在为我的存储库实现制定一个通用提供程序,这个提供程序将由BaseController(ASP.NET MVC 2)用于低级对象。这些对象具有常用的操作,例如激活/取消激活/删除/编辑,所以我会一直使用相同的属性。问题是,由于我不知道T是什么,我显然无法访问它的属性。在通用提供程序中如何查找和编辑T的属性? (C#)

所以,我的问题是,有人可以告诉我如何从对象中获取所需的属性。我见过一些人在谈论反思,其他表达树,我都不知道如何使用。我有一个通用的存储库,我相信使用表达式树(从一些网站复制它),但是,我不知道我在做什么...如果它有帮助,这就是我'到目前为止:

public class Provider<T> where T : class { 
    private readonly Repository<T> Repository = null; 

    public Provider(
     Repository<T> Repository) { 
     this.Repository = Repository; 
    } 

    public void Activate(
     int Id) { 
     T Entity = this.Repository.Select(Id); 

     // Need to get the property here, change it and move on... 

     this.Repository.Submit(); 
    } 
} 

我会很感激这方面的帮助。

+0

“底层对象”是否从通用接口或基类c继承姑娘?如果是这样,你可以限制'T'; '在哪T:IInterface'。 – porges 2010-11-19 04:10:59

+0

他们没有。他们都是Linq to Sql类的,他们自己... – Gup3rSuR4c 2010-11-19 04:13:26

回答

4

如果这些类具有共同的操作,听起来像他们应该从同一个基地继承或实现相同的接口,更正吗?如果是这样,使用该接口/碱作为约束对于T

public class Provider<T> where T : ICommonInterface 

你将有然后编译时访问由接口或基类提供的共享成员。

+0

它会工作,但他们不从基类继承。他们都是Linq to Sql对象。 – Gup3rSuR4c 2010-11-19 04:13:59

+4

@Alex,不太了解Linq-to-SQL。但生成的类是部分的,正确的?这意味着在最坏的情况下,您可以为这些类创建其他分支并指出那里的通用接口。我不知道,你可能会直接做出这部分数据模型。这是一个值得探索的思想。 – 2010-11-19 04:21:41

+1

Anthony是100%正确的 - 我们之前已经遵循这种模式,并且实现了部分类的'另一面'以从基类中添加额外的行为/实现接口/继承。当您重新生成DBML时,它只更新它自己的.cs文件,而不是提供部分另一半的.cs文件。 – 2010-11-19 04:32:37

0

最好的解决方案是给对象一个通用的基类型,并将类型参数T约束为该类型。然后,你将有机会获得在编译时的方法或公共基类型的属性:

public class Provider<T> where T : ICommon 
{ 
    ... 
} 

public class Provider<T> where T : CommonBase 
{ 
    ... 
} 

如果这是不可能的,那么没有一个共同的基本类型最好的,你可以不要在对象是反映查找和调用,你有兴趣的财产:

public void Activate(int Id) 
{ 
    T entity = this.Repository.Select(Id); 

    // Interrogate the type of the entity and get the property called "MyPropertyName" 
    PropertyInfo pi = entity.GetType().GetProperty("MyPropertyName"); 

    // Invoke the property against the entity instance - this retrieves the 
    // value of the property. 
    var value = (YourType)(pi.GetValue(entity, null)); 

    // Do somethign with the value...   

    this.Repository.Submit(); 
} 

我要补充一点,反映比较昂贵的,你也失去了编译实时验证。但在这类情况下,这很方便。

你可以通过调用获取与方法工作的一个MethodInfo对象:

MethodInfo mi = entity.GetType().GetMethod("MyMethodName"); 
0

你可以做一个动作

public void Activate(int Id, Action<T> doSomething) 
{ 
    T Entity = this._repository.Select(Id); 
    // Need to get the property here, change it and move on... 
    doSomething(Entity); 
    _repository.Submit(); 
} 

然后(通过拉姆达在这个例子中)使用操作委托属性将在调用激活时知道:

prov.Activate(5, x => x.Address = "fgfgf"); 
相关问题