[英]C# How to return an instance of the type of subclass from function?
我有一堆類,它們構成了項目的各種變體。 我目前有這樣的課程:
public class Item {
public ItemFile file { get; set;}
public ItemCalendar calendar { get; set;}
public ItemWebsite website { get; set;}
}
ItemFile等是使用實體框架制作的類,並映射到提供與該項目類型有關的信息的數據庫表。 item類僅具有實際實例化的內部屬性之一。
我可以看到項目數量增加到25個左右或更多。 我不認為制作包含25個屬性的視圖模型是不對的,其中24個為空,只有一個不為空。
我想要一些可以與實體框架一起使用的東西,並返回一個只能返回其實際類型的類。 因此,如果我要求該項目的變體,我將取回ItemFile用於文件,而ItemCalendar用於日歷。
我已經嘗試過這樣的事情:
public class Item
{
public ItemBase item { get; set; }
}
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
但是然后我不知道如何將ItemFile作為public typeName返回是一個錯誤。
然后,我嘗試:
public class Item
{
public ItemBase<ItemFile> item { get; set; }
}
public class ItemBase<T>
{
public T ItemInstance { get; set; }
}
但是要使其正常工作,我必須在item類的<>中對FileItem進行硬核化,這可以使您事先了解類型。
反正有什么要使它起作用? 值得一提的是,如果它可以與實體框架一起使用,那么我將從那里撤回這些類。 最糟糕的是,如果它在實體框架上不起作用,我可以將其全部提取,然后將其轉換為可以回答問題的形式。
如果問題標題錯誤,請隨時進行編輯。 我不確定怎么問。
tl; dr版本:我希望能夠使用不使用<>傳入的類型從函數返回多種類型的類。
編輯1:
我忘了展示我的繼承示例。 我已經嘗試過了,但是也遇到了與上面類似的問題。
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
public class ItemFile : ItemBase
{
public String FileName { get; set; }
}
public class Test
{
public void testFunction()
{
//Made this just so the compiler didn't complain.
ItemFile testFile = new ItemFile();
//I can use a function to get the item base.
ItemBase baseItem = testFile;
//How do I do this? Use a function to get the ItemFile from the instance.
ItemFile finalItem = baseItem.GetInstance();
}
}
我相信這與您將要實現的目標差不多。
using System;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
EFTypeData itemData = GetItemData();
var asmName = Assembly.GetExecutingAssembly().GetName().Name;
var type = Type.GetType($"ConsoleApplication1.{itemData.TypeName}, {asmName}");
var instance = Activator.CreateInstance(type);
var item = new Item<Object>()
{
ItemBase = instance
};
}
private static EFTypeData GetItemData()
{
return new EFTypeData() { TypeName = "ItemFile" };
}
}
class EFTypeData
{
public string TypeName { get; set; }
}
class Item<T> where T: class
{
public T ItemBase { get; set; }
}
class ItemFile
{
public string FileName { get; set; }
}
}
給定字符串“ ItemFile”,這將創建一個實例並將其分配給Item。 如果運行此程序並檢查item
,則有
最大的警告是,在編譯時,您擁有的只是一個Object作為您的ItemBase。 而且,如果不對您的Type進行硬編碼(即var item = new Item<ItemFile>();
),您將永遠不會了解更多。
就是說,使用這種方法,您非常清楚地可以遍歷字段,並使用反射進行遍歷。 但這是這種運行時對象操作級別的限制。
我希望能夠使用不使用<>傳入的類型從函數返回多種類型的類。
<>(泛型)是一種機制,通過該機制,函數可以顯式返回多個類型。 如果沒有泛型,該函數將返回其返回的任何類型。
object SomeFunction() // Returns an object
ItemBase SomeOtherFunction () // returns ItemBase
在上面的示例中, SomeFunction
仍然可以返回任何類型(因為所有類型都繼承自object
。)但是它不是明確的。 您只知道它是一個object
。
同樣, SomeOtherFunction
可以返回ItemBase
或從ItemBase
繼承的任何類。 但這就是您所知道的。
理想情況下,您不想讓函數返回一種類型(例如object
或ItemBase
),然后將函數的結果轉換為另一種更特定的類型。 該函數應該返回您想要的,並且您應該想要該函數返回的。 泛型對此有所幫助。 例如:
public TItem Instance<TItem>() where TItem : ItemBase
允許函數返回指定的類型,只要它是ItemBase
或從一個繼承即可。
最后的評論似乎很奇怪或沒用,但這是事實。 如果您發現上述規則不起作用,並且需要能夠做一些您無法做或不應該做的事情,請回頭重新考慮為什么要這樣做。 那才是真正的問題所在。
這意味着您可能需要退后一步,使自己脫離試圖使用該語言的情況。 您想完成什么?如何以一種適合該語言而不是違背該語言的方式來實現?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.