C# 在强制转换两个相同的对象时无法强制转换对象
在我的模型中,我有三个相同的类视图:UViews、TotalConfiguration和StatsViewModel。它们各自具有相同的属性:C# 在强制转换两个相同的对象时无法强制转换对象,c#,asp.net,entity-framework,linq,casting,C#,Asp.net,Entity Framework,Linq,Casting,在我的模型中,我有三个相同的类视图:UViews、TotalConfiguration和StatsViewModel。它们各自具有相同的属性: public class Views { public int idProject {get;set;} public int January { get; set; } public int February { get; set; } public int March { ge
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;
}
我尝试这样做,但在这种情况下,我得到了相同的错误:
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调用泛型转换不会反映用户定义的转换。因此,上述三种解决方案中的任何一种仍然不适用于以下内容:
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;
}
C不做duck类型。不同类的对象具有相同的属性是不够的——它们仍然是不同的类型。您可能正在寻找类似Automapper的东西。从编译器的角度来看,您的三种类型没有任何共同之处。然而,从语义的角度来看。。。您可以引入自定义强制转换运算符,并使用Selectx=>MyTypex而不是.cast。@HimBromBeere cast基本上在内部执行MyTypex。@DavidG也用于用户定义的强制转换吗?我怀疑不是这样。@himbrombere你所说的用户定义类型转换是什么意思?我说的是
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;
}