You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classBaseViewModel<TModel>{publicTModelModel{get;set;}}classUser{publicstringName{get;set;}publicbyteAge{get;set;}}classMainViewModel:BaseViewModel<User>{publicstringId{get;set;}}staticclassBaseViewModelExtensions{publicstaticboolCheck<TB,TM>(thisTBbVm,Func<TM,bool>check)whereTB:BaseViewModel<TM>{returncheck(bVm.Model);}publicstaticvoidCheck2<TB,TM>(thisTBbVm)whereTB:BaseViewModel<TM>{}}staticclassBaseViewModelEnhancedExtensions<TB,TM>whereTB:BaseViewModel<TM>{publicstaticvoidCheck(TBbVm){}}staticclassTest{publicstaticvoidRun(){varmvm=newMainViewModel{Model={Name="O",Age=30},Id="RIH"};mvm.Check<MainViewModel,User>(m =>m.Age>10);BaseViewModelEnhancedExtensions<MainViewModel,User>.Check(mvm);// Due to limitation of C# generic inferred as described in its Specifications: `7.5.2.1 - 7.5.2.6`// we can not do next// mvm.Check2();// BaseViewModelEnhancedExtensions.Check(mvm);}}
First Solution: we will introduce Self Property to enhance types inferring
Second Solution: We will introduce ISelf interface
// TSub should increases as many as sub types may needed [TSub1, TSub2]interfaceISelf<TSub,TThis>whereTThis:ISelf<TSub,TThis>{(TThisth,TSubsub)Self{get;}}interfaceIBaseViewModel<TModel,TSelf>:ISelf<TModel,TSelf>whereTSelf:ISelf<TModel,TSelf>{TModelModel{get;set;}}// helperclassUser{publicstringName{get;set;}publicbyteAge{get;set;}}
#region Second Solution - method 1
classBaseViewModel<TModel>:IBaseViewModel<TModel,BaseViewModel<TModel>>{publicTModelModel{get;set;}public(BaseViewModel<TModel>th,TModelsub)Self=>(this,Model);}classMainViewModel:BaseViewModel<User>{publicstringId{get;set;}}
#endregion
#region Second Solution - method 2
classBaseViewModel2<TModel,TThis>:IBaseViewModel<TModel,TThis>whereTThis:BaseViewModel2<TModel,TThis>{publicTModelModel{get;set;}public(TThisth,TModelsub)Self=>((TThis)this,Model);}classMainViewModel2:BaseViewModel2<User,MainViewModel2>{publicstringId{get;set;}}
#endregion
staticclassBaseViewModelExtensions{
#region Use Hard Constraints
publicstaticboolWork<TB,TM>(this(TBvm,TMm)self,Func<TM,bool>exe)whereTB:BaseViewModel2<TM,TB>{returnexe(self.vm.Model);}publicstaticboolWork<TM>(this(BaseViewModel<TM>vm,TMm)self,Func<TM,bool>exe){returnexe(self.vm.Model);}
#endregion
#region Use Mixed Constraints: ISelf + Hard Types
publicstaticboolFun<TM>(thisISelf<TM,BaseViewModel<TM>>b,Func<TM,bool>exe){returnexe(b.Self.sub);}publicstaticboolFun<TB,TM>(thisISelf<TM,TB>b,Func<TM,bool>exe)whereTB:BaseViewModel2<TM,TB>{returnexe(b.Self.sub);}
#endregion
#region Hit the edge of genericity
// the most generic one : will work for booth.publicstaticboolMostFun<TB,TM>(thisISelf<TM,TB>b,Func<TM,bool>exe)whereTB:ISelf<TM,TB>{returnexe(b.Self.sub);}
#endregion
}staticclassTest{publicstaticvoidRun(){varmvm=newMainViewModel{Model={Name="O",Age=30},Id="RIH"};varmvm2=newMainViewModel2{Model={Name="O",Age=30},Id="RIH"};
#region HC
mvm.Self.Work(s =>string.IsNullOrEmpty(s.Name));mvm2.Self.Work(s =>string.IsNullOrEmpty(s.Name));
#endregion
#region MC
mvm.Fun(s =>string.IsNullOrEmpty(s.Name));mvm2.Fun(s =>string.IsNullOrEmpty(s.Name));
#endregion
#region MG
mvm.MostFun(s =>string.IsNullOrEmpty(s.Name));mvm2.MostFun(s =>string.IsNullOrEmpty(s.Name));
#endregion
}}