簡體   English   中英

C#如何從函數返回子類類型的實例?

[英]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繼承的任何類。 但這就是您所知道的。

理想情況下,您不想讓函數返回一種類型(例如objectItemBase ),然后將函數的結果轉換為另一種更特定的類型。 該函數應該返回您想要的,並且您應該想要該函數返回的。 泛型對此有所幫助。 例如:

public TItem Instance<TItem>() where TItem : ItemBase

允許函數返回指定的類型,只要它是ItemBase或從一個繼承即可。

最后的評論似乎很奇怪或沒用,但這是事實。 如果您發現上述規則不起作用,並且需要能夠做一些您無法做或不應該做的事情,請回頭重新考慮為什么要這樣做。 那才是真正的問題所在。

這意味着您可能需要退后一步,使自己脫離試圖使用該語言的情況。 您想完成什么?如何以一種適合該語言而不是違背該語言的方式來實現?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM