如何从基于给定类型的泛型方法 return new class 实例?
How to return new class instance from generic method based on given types?
我有两个 parent 类:Item
和 ItemData
。从第一个开始,我制作诸如 WeaponItem
之类的项目,从第二个开始,我制作诸如 WeaponData
.
之类的相应数据
每个项目类型在其构造函数中采用相同类型的数据(例如:创建 WeaponItem
时需要 WeaponData
)。
我有以下方法:
public static T CreateNewItem<T, DT>(ItemData data) where T : Item where DT : ItemData
{
if (data == null) return null;
if (data is DT dt)
{
//determine type of T
Type itemType = typeof(T);
if (itemType = typeof(WeaponItem))
{
//make a new weapon item...
WeaponItem new_weapon = new WeaponItem(dt); //error!
return new_weapon;
}
if (itemType = typeof(ArmorItem))
{
//make a new armor item...
}
//etc...
}
return null;
}
我这样称呼它:
CreateNewItem<WeaponItem, WeaponData>(data);
注意:data
是 ItemData
类型或某种继承类型(例如 WeaponData
)。
此方法需要两种类型:一种用于 Item
,一种用于 ItemData
。我有几件物品(武器、盔甲等...),我根据我提供的类型创建物品。我还想检查我使用的数据:data is DT dt
从我传递的数据中获取 WeaponData
,如果转换失败则 null
。
当我尝试执行 WeaponItem new_weapon = new WeaponItem(dt);
时,出现以下错误:
Argument 1: cannot convert from 'DT' to 'WeaponData' [Assembly-CSharp]csharp(CS1503)
我试过像这样将 dt
转换为 WeaponData
:WeaponItem new_weapon = new WeaponItem((WeaponData)dt);
,但我得到了类似的错误
Cannot convert type 'DT' to 'WeaponData' [Assembly-CSharp]csharp(CS0030)
同样,使用 data
代替 dt
会产生错误。
是否可以不用每次都检查类型就可以解决这个问题?
你的设计对我来说有点反直觉,所以让我们从通用方法的一个极其简单的版本开始,然后从那里开始。您可以复制和编译此代码。
您也可以点击 this link 然后点击 运行 按钮。
我想说这里最大的优势是泛型方法变成了一行代码。您可以根据需要添加任意数量的项目,并且永远不会更改该方法。而您的实施变得越来越复杂。
代码:
public class ItemData
{
public string ItemName { get; init; }
}
public class WeaponData : ItemData { }
public class Item
{
public ItemData Data { get; init; }
public Item(ItemData data)
{
Data = data;
}
}
public class WeaponItem : Item
{
public WeaponItem(WeaponData data) : base(data) { }
public override string ToString() => Data.ItemName;
}
public static T CreateNewItem<T, TD>(TD data)
where T : Item
where TD : ItemData
{
return (T)Activator.CreateInstance(typeof(T), data);
}
static void Main(string[] args)
{
var bestWeaponDataEver = new WeaponData() { ItemName = "Dragon Slayer" };
var amazingWeapon = CreateNewItem<WeaponItem, WeaponData>(bestWeaponDataEver);
Console.WriteLine(amazingWeapon);
}
输出:
Dragon Slayer
另一个很大的区别是您接受的是特定类型 ItemData
,它应该是通用类型 DT
。否则为什么 DT
甚至存在?这可能把你绊倒了。
public static T CreateNewItem<T, DT>(ItemData data) where T : Item where DT : ItemData
应该是这个
public static T CreateNewItem<T, DT>(DT data) where T : Item where DT : ItemData
请注意 WeaponItem
的构造函数只接受 WeaponData
。因此,尽管使用了简单的通用方法,但您无法使用 ItemData
或 CakeData
或其他任何基础来创建武器。
如果您不确定如何扩展此评论,我会尽力提供进一步帮助。
我有两个 parent 类:Item
和 ItemData
。从第一个开始,我制作诸如 WeaponItem
之类的项目,从第二个开始,我制作诸如 WeaponData
.
之类的相应数据
每个项目类型在其构造函数中采用相同类型的数据(例如:创建 WeaponItem
时需要 WeaponData
)。
我有以下方法:
public static T CreateNewItem<T, DT>(ItemData data) where T : Item where DT : ItemData
{
if (data == null) return null;
if (data is DT dt)
{
//determine type of T
Type itemType = typeof(T);
if (itemType = typeof(WeaponItem))
{
//make a new weapon item...
WeaponItem new_weapon = new WeaponItem(dt); //error!
return new_weapon;
}
if (itemType = typeof(ArmorItem))
{
//make a new armor item...
}
//etc...
}
return null;
}
我这样称呼它:
CreateNewItem<WeaponItem, WeaponData>(data);
注意:data
是 ItemData
类型或某种继承类型(例如 WeaponData
)。
此方法需要两种类型:一种用于 Item
,一种用于 ItemData
。我有几件物品(武器、盔甲等...),我根据我提供的类型创建物品。我还想检查我使用的数据:data is DT dt
从我传递的数据中获取 WeaponData
,如果转换失败则 null
。
当我尝试执行 WeaponItem new_weapon = new WeaponItem(dt);
时,出现以下错误:
Argument 1: cannot convert from 'DT' to 'WeaponData' [Assembly-CSharp]csharp(CS1503)
我试过像这样将 dt
转换为 WeaponData
:WeaponItem new_weapon = new WeaponItem((WeaponData)dt);
,但我得到了类似的错误
Cannot convert type 'DT' to 'WeaponData' [Assembly-CSharp]csharp(CS0030)
同样,使用 data
代替 dt
会产生错误。
是否可以不用每次都检查类型就可以解决这个问题?
你的设计对我来说有点反直觉,所以让我们从通用方法的一个极其简单的版本开始,然后从那里开始。您可以复制和编译此代码。
您也可以点击 this link 然后点击 运行 按钮。
我想说这里最大的优势是泛型方法变成了一行代码。您可以根据需要添加任意数量的项目,并且永远不会更改该方法。而您的实施变得越来越复杂。
代码:
public class ItemData
{
public string ItemName { get; init; }
}
public class WeaponData : ItemData { }
public class Item
{
public ItemData Data { get; init; }
public Item(ItemData data)
{
Data = data;
}
}
public class WeaponItem : Item
{
public WeaponItem(WeaponData data) : base(data) { }
public override string ToString() => Data.ItemName;
}
public static T CreateNewItem<T, TD>(TD data)
where T : Item
where TD : ItemData
{
return (T)Activator.CreateInstance(typeof(T), data);
}
static void Main(string[] args)
{
var bestWeaponDataEver = new WeaponData() { ItemName = "Dragon Slayer" };
var amazingWeapon = CreateNewItem<WeaponItem, WeaponData>(bestWeaponDataEver);
Console.WriteLine(amazingWeapon);
}
输出:
Dragon Slayer
另一个很大的区别是您接受的是特定类型 ItemData
,它应该是通用类型 DT
。否则为什么 DT
甚至存在?这可能把你绊倒了。
public static T CreateNewItem<T, DT>(ItemData data) where T : Item where DT : ItemData
应该是这个
public static T CreateNewItem<T, DT>(DT data) where T : Item where DT : ItemData
请注意 WeaponItem
的构造函数只接受 WeaponData
。因此,尽管使用了简单的通用方法,但您无法使用 ItemData
或 CakeData
或其他任何基础来创建武器。
如果您不确定如何扩展此评论,我会尽力提供进一步帮助。