在我的模型中,我有三个相同的类(视图,UViews, TotalConfiguration和StatsViewModel)。它们都有相同的属性:
public class Views
{
public int idProject {get;set;}
public int January { get; set; }
public int February { get; set; }
public int March { get; set; }
public int April { get; set; }
public int May { get; set; }
public int June { get; set; }
public int July { get; set; }
public int August { get; set; }
public int September { get; set; }
public int October { get; set; }
public int November { get; set; }
public int December { get; set; }
}
我想通过上下文从数据库(从视图或UViews或TotalConfiguration)获取数据,并将结果保存到列表类型StatsViewModel:
//some code
var customer = _context.Get<UViews>(x => x.Projects.ProjectsUser.Where(x => x.IdUser == userId).Any());
//some code
public StatsViewModel Get<T>(Expression<Func<T, bool>> predicate)
where T : class
{
List<StatsViewModel> listItem = new List<StatsViewModel>();
StatsViewModel item = new StatsViewModel();
var listFromDatabase = Set<T>().Where(predicate).ToList();
listItem.AddRange(listFromDatabase.Cast<StatsViewModel>());
item = listItem.FirstOrDefault();
return item;
}
代码工作完美行listItem.AddRange(listFromDatabase.Cast<StatsViewModel>());
。当我尝试转换listFromDatabase列到I got error:
System.InvalidCastException: 'Unable to cast object
of type 'Housematica.Data.Data.CMS.Statistics.UViews'
to type 'Housematica.Intranet.ViewModel.StatsViewModel'.'
我试着这样做,但在这种情况下,我得到了同样的错误:
var listFromDatabase = Set<T>().Where(predicate).ToList().Cast<StatsViewModel>();
从编译器的角度来看,这些类型没有任何内容共同之处。仅仅因为两个类型具有相同的属性并不能使它们成为相同的类型。当类通常也有方法时,这变得更加清楚。. 如何指明两个类具有相同的方法?想象这两个:
class ClassA
{
int MyProperty { get; set; }
void DoSomething() => { Console.WriteLine(MyProperty); }
}
class ClassB
{
int MyProperty { get; set; }
void DoSomething() => { Console.WriteLine("Hello world"); }
}
上述两个类是否相等,因为它们具有相同的成员?很难说。当然它们的属性是匹配的,但是它们的方法呢?这两个相等吗?嗯,从正式的角度来看,只要考虑到他们的签名,人们就会认为是这样。然而,他们做的事情完全不同。因此,编译器不可能假设您的两种类型是否实际上表示相同的东西,这就是为什么它不(隐式地)允许这样的转换。
但是你还有很多其他的机会。最简单的方法是创建一些映射函数:
ClassA Map(ClassB b) => new ClassA { MyProperty = b.MyProperty };
现在你可以这样调用它:
myList.Select(x => Map(x));
另一种方法是复制构造函数:
class ClassA
{
public ClassA(ClassB b) { this.MyProerty = b.MyProperty }
}
可以用Select
-语句调用:
myList.Select(x => new ClassA(x));
最后,您可以引入一些隐式或显式转换:
static explicit operator ClassA(ClassB b) => new ClassA { MyProperty = b.MyProperty };
,这是唯一可以用于强制转换的:
myList.Select(x => (ClassA)x);
但是要注意,从IEnumerable<T>
调用泛型Cast<T>
不会反映用户定义的强制转换。因此,下面的代码仍然不能用于上述三种解决方案中的任何一种:
myList.Cast<ClassA>();
最后我找到了类似JsonConvert的东西,我在我的代码中使用它:
public StatsViewModel Get<T>(Expression<Func<T, bool>> predicate) where T : class
{
StatsViewModel item = new StatsViewModel();
var listFromDatabase = Set<T>().Where(predicate).ToList();
List<StatsViewModel> targetlst = JsonConvert.DeserializeObject<List<StatsViewModel>>
(JsonConvert.SerializeObject(listFromDatabase));
item = targetlst.FirstOrDefault();
return item;
}