通过通用类型参数访问属性我正在尝试为我的模型创建一个通用存储库。目前我有3个不同的模型,它们之间没有关系。(联系人、笔记、提醒)。classRepositorywhereT:class{publicIQueryableSearchExact(stringkeyword){//有没有办法让下面的行通用//returndb.ContactModels.Where(i=>i.Name==keyword)//I还尝试了db.GetTable().Where(i=>i.Name==keyword)//但是变量i没有Name属性,因为它只会在运行时知道它//db也有一个方法ITableGetTable(TypemodelType)butdon'tthinkthatifthatwouldhelpme}}在MainViewModel中,我像这样调用搜索方法:Repository_contactRepository=newRepository();publicvoidSearch(stringkeyword){varfilteredList=_contactRepository.SearchExact(keyword).ToList();}解释:最后是Ray的动态表达解决方案:publicIQueryableSearchExact(stringsearchKeyword,stringcolumnName){ParameterExpressionparam=Expression.Parameter(typeof(TModel),"i");左表达式=Expression.Property(param,typeof(TModel).GetProperty(columnName));Expressionright=Expression.Constant(searchKeyword);表达式expr=Expression.Equal(左,右);}query=db.GetTable().Where(Expression.Lambda(expr,param));接口方案如果你可以给一个对象添加一个接口,你就可以使用那个接口,例如,你可以定义:publicinterfaceIName{stringName{get;}}然后你的存储库可以声明为:}}备用接口解决方案或者,您可以将“where”放在带有第二个通用参数的SearchExact方法上:.Where(i=>i.Name==keyword);这允许Repository类与不实现IName的对象一起使用,而SearchExact方法只能与实现IName的对象一起使用。反射解决方案如果你不能给你的对象添加一个类似IName的接口,你可以使用反射:classRepositorywhereT:class{staticPropertyInfo_nameProperty=typeof(T).GetProperty("Name");publicIQueryableSearchExact(stringkeyword){returndb.GetTable().Where(i=>(string)_nameProperty.GetValue(i)==keyword);这比使用接口慢,但有时这是唯一的方法。关于接口解决方案的更多说明以及为什么要使用它在您的评论中,您提到您不能使用该接口,但没有解释原因。你说“这三个模型之间没有任何共同点。所以我认为不可能从它们中创建一个接口。”根据您的问题,我了解到所有三个模型都有一个“名称”属性。在这种情况下,接口可以在所有三个上实现。只需如图所示实现接口并为三个类定义中的每一个实现“,IName”。这将为您提供本机查询和SQL生成的最佳性能。即使有问题的属性并不都称为“名称”,您仍然可以通过向每个属性添加“名称”属性并使其getter和setter访问其他属性来使用接口解决方案。表达式方案如果IName解决方案不起作用并且您需要SQL转换才能起作用,这可以通过使用表达式构建LINQ查询来完成。工作越多,本地使用的效率就越低,但可以很好地转换为SQL。代码将是这样的:returndb.GetTable().Where(Expression.Lambda>(Expression.Equal(Expression.Invoke(Expression.Constant(getNameExpression),param),Expression.Constant(keyword),param));}}因此会被调用:repository.SearchExact("TextToFind",i=>i.Name)如果你有能力添加一个绝对优越的接口但如果由于某种原因你不能向这些类添加接口(部分一个你不能编辑的类库或其他)那么你也可以考虑传递一个Func在那里你可以告诉它如何获取名称。例如:classRepository{publicIQueryableSearchExact(stringkeyword,FuncgetSearchField){returndb.GetTable().Where(i=>getSearchField(i)==keyword);然后你必须调用它:varfilteredList=_contactRepository.SearchExact(keyword,cr=>cr.Name).ToList();除了这两个选项之外,您始终可以考虑使用反射来访问Name属性而无需任何接口,但这有一个缺点,即没有编译时检查来确保您传递的类实际上具有Name属性。作为副作用,LINQ不会转换为SQL,过滤将在.NET中进行(这意味着SQL服务器可能会接受更多的点击)。您也可以使用动态LINQ查询来实现这种SQL方面的效果,但它具有上面列出的相同的非类型安全问题。以上就是C#学习教程:通过Generic类型参数访问属性共享的所有内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处: