C# 如何使用泛型创建流畅的界面
我想创建一个流畅的界面,可以这样使用:C# 如何使用泛型创建流畅的界面,c#,generics,expression,fluent-interface,C#,Generics,Expression,Fluent Interface,我想创建一个流畅的界面,可以这样使用: void Main() { ModelStateMappings.MapDomainModel<Book>().MapViewModel<BookViewModel>() .Properties(book => book.Author, vm => vm.AuthorsName) .Properties(book => book.Price, vm => vm.Book
void Main() {
ModelStateMappings.MapDomainModel<Book>().MapViewModel<BookViewModel>()
.Properties(book => book.Author, vm => vm.AuthorsName)
.Properties(book => book.Price, vm => vm.BookPrice);
ModelStateMappings.MapDomainModel<Store>().MapViewModel<StoreViewModel>()
.Properties(store => store.Owner, vm => vm.OwnersName)
.Properties(store => store.Location, vm => vm.Location);
}
void Main(){
ModelStateMappings.MapDomainModel().MapViewModel()
.Properties(book=>book.Author,vm=>vm.AuthorsName)
.Properties(book=>book.Price,vm=>vm.BookPrice);
ModelStateMappings.MapDomainModel().MapViewModel()
.Properties(store=>store.Owner,vm=>vm.OwnersName)
.Properties(store=>store.Location,vm=>vm.Location);
}
我想最终得到一个类似这样的收藏:
static class ModelStateaMappings {
private static IList<ModelMappings> mappings;
// other methods in here to get it working
}
class ModelMappings {
public Type DomainModelType {get;set;}
public Type ViewModelType {get;set;}
public IList<PropertyMapping> PropertyMappings {get;set;}
}
class PropertyMapping {
public Expression<Func<object, object>> DomainProperty {get;set;}
public Expression<Func<object, object>> ViewModelProperty {get;set;}
}
public class NamesBuilder
{
private List<string> _names = new List<string>();
public NamesBuilder AddName(string name)
{
_names.Add(name);
return this;
}
}
静态类modelstatemappings{
私有静态IList映射;
//这里还有其他方法可以让它工作
}
类模型映射{
公共类型DomainModelType{get;set;}
公共类型ViewModelType{get;set;}
公共IList属性映射{get;set;}
}
类属性映射{
公共表达式域属性{get;set;}
公共表达式ViewModelProperty{get;set;}
}
我无法完成上面的工作,但工作方式类似,但我并不特别喜欢如何设置流畅的界面。我宁愿让它像上面那样读。您可以通过以下代码实现它
static class ModelStateMappings
{
public static DomainModelMapping<TDomainModel> MapDomainModel<TDomainModel>()
{
// edit the constructor to pass more information here if needed.
return new DomainModelMapping<TDomainModel>();
}
}
public class DomainModelMapping<TDomainModel>
{
public ViewModelMapping<TDomainModel, TViewModel> MapViewModel<TViewModel>()
{
// edit the constructor to pass more information here if needed.
return new ViewModelMapping<TDomainModel, TViewModel>();
}
}
public class ViewModelMapping<TDomainModel, TViewModel>
{
public ViewModelMapping<TDomainModel, TViewModel>
Properties<TDomainPropertyType, TViewModelPropertyType>(
Expression<Func<TDomainModel, TDomainPropertyType>> domainExpr,
Expression<Func<TViewModel, TViewModelPropertyType>> viewModelExpr)
{
// map here
return this;
}
}
静态类ModelStateMappings
{
公共静态DomainModelMapping MapDomainModel()
{
//如果需要,请编辑构造函数以在此处传递更多信息。
返回新的DomainModelMapping();
}
}
公共类DomainModelMapping
{
公共ViewModelMapping MapViewModel()
{
//如果需要,请编辑构造函数以在此处传递更多信息。
返回新的ViewModelMapping();
}
}
公共类ViewModelMapping
{
公共视图模型映射
性质(
表达式域表达式,
表达式(viewModelExpr)
{
//地图在这里
归还这个;
}
}
您不必指定所有以前设置的泛型类型,因为它们已作为返回类型的泛型参数被记住。可以跳过属性
方法调用的泛型参数,因为编译器将推断这些参数。而且,与在任何地方使用object
s相比,您都能获得更好的键入效果
当然,这是最简单的版本。您可以在这些类型之间传递更多信息,因为您可以指定如何创建下一个必需的类型
它还使得在不调用
MapDomainModel
的情况下调用MapViewModel
首先是不可能的(只要将构造函数设置为内部
并在单独的dll中关闭所有内容),这应该是一件好事。有两种常见的方法来创建流畅的界面
一种方法是添加到正在构建的类的当前实例中,并从每个方法返回this
大概是这样的:
static class ModelStateaMappings {
private static IList<ModelMappings> mappings;
// other methods in here to get it working
}
class ModelMappings {
public Type DomainModelType {get;set;}
public Type ViewModelType {get;set;}
public IList<PropertyMapping> PropertyMappings {get;set;}
}
class PropertyMapping {
public Expression<Func<object, object>> DomainProperty {get;set;}
public Expression<Func<object, object>> ViewModelProperty {get;set;}
}
public class NamesBuilder
{
private List<string> _names = new List<string>();
public NamesBuilder AddName(string name)
{
_names.Add(name);
return this;
}
}
如果我看到这段代码,我希望namebuilder1
和namebuilder2
都只有一个名称,而namebuilder
不会有任何名称。但是,实现在所有三个变量中都有这两个名称,因为它们是同一个实例
实现fluent接口的更好方法是在构建器类上创建一个链,该类将被延迟评估,以便在构建完成后创建最终的类。然后,如果你在建筑过程的中间分支,你可能会犯错误。
下面是我希望编写的代码类型:
var bookMap =
ModelStateMappings
.Build<Book, BookViewModel>()
.AddProperty(book => book.Author, vm => vm.AuthorsName)
.AddProperty(book => book.Price, vm => vm.BookPrice)
.Create();
var bookStore =
ModelStateMappings
.Build<Store, StoreViewModel>()
.AddProperty(store => store.Owner, vm => vm.OwnersName)
.AddProperty(store => store.Location, vm => vm.Location)
.Create();
var bookMap=
模型状态映射
.Build()
.AddProperty(book=>book.Author,vm=>vm.AuthorsName)
.AddProperty(book=>book.Price,vm=>vm.BookPrice)
.Create();
var书店=
模型状态映射
.Build()
.AddProperty(store=>store.Owner,vm=>vm.OwnersName)
.AddProperty(store=>store.Location,vm=>vm.Location)
.Create();
实现此功能的代码比“名称”示例稍微复杂一些
公共静态类ModelStateMappings
{
公共静态生成器Build()
{
返回新的生成器();
}
公共类生成器
{
公共生成器(){}
公共建筑商地址属性(
表达式域映射,
表达式(视图模型映射)
{
返回新的BuilderProperty(this、domainMap、viewModelMap);
}
公共虚拟地图创建()
{
返回新映射();
}
}
公共类生成器属性:生成器
{
私人建筑商——以前的建筑商;
私有表达式_domainMap;
私有表达式_viewModelMap;
公共建筑财产(
建筑商之前的建筑商,
表达式域映射,
表达式(视图模型映射)
{
_previousBuilder=previousBuilder;
_domainMap=domainMap;
_viewModelMap=viewModelMap;
}
公共覆盖映射创建()
{
var map=_previousBuilder.Create();
/*将当前映射添加到映射类的代码*/
返回图;
}
}
}
这种类型的生成器的另一个优点是还可以维护强类型属性字段
当然,您需要为
Create
方法中的映射输入正确的代码。您现在拥有的界面是什么样子的?是什么具体的问题阻止了您使它看起来像您想要的那样?我不知道如何获得泛型推理,一直到.Properties()方法,同时传递这两种类型。我希望这样做的方式是一次传递每个泛型,然后在Property()方法中将它们组合在一起。听起来您需要一个类型数组。你看过吗?我看过automapper,那不是我需要的。我并不是真的用它来映射模型之间的属性。。我想用它来获取域模型中哪些属性与vie中的属性相关的表达式