C#如何从函数中返回子类类型的实例?

时间:2017-09-25 15:41:00

标签: c# entity-framework class inheritance

我有一堆类来制定各种各样的项目。我目前有一个这样的课程:

public class Item {
    public ItemFile file { get; set;}
    public ItemCalendar calendar { get; set;}
    public ItemWebsite website { get; set;}
}

ItemFile等是使用Entity Framework制作的类,并映射到数据库表,提供与该类型的项相关的信息。 item类只有一个实际实例化的内部属性。

我可以看到物品数量增长到25左右或更多。我觉得让视图模型包含25个属性是正确的,其中24个属性为null,只有一个属性为null。

我想要一些可以使用实体框架的东西,并返回一个只能返回它的实际类型的类。因此,如果我要求更改项目,我会返回ItemFile for files和ItemCalendar for calendars。

我尝试过这样的事情:

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; }
}

但为了让它发挥作用,我不得不在&lt;&gt;中硬核FileItem。在项目类上,它可以追溯到事先了解类型。

有没有让这个工作?奖励点是否可以与实体框架一起使用,因为我从那里撤回了类。如果它没有工作实体框架,最糟糕的是最糟糕的是我可以将其全部拉出然后将其转换为回答问题的形式。

如果问题的标题有误,请随时编辑。我不确定该怎么问。

tl; dr version:我希望能够使用不使用&lt;&gt;传递的类型从函数返回多种类型的类。

编辑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();
    }
}

2 个答案:

答案 0 :(得分:1)

我相信这与你将会得到的一样接近。

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,你就有了 debug output

对此的一个重要警告是,在编译时,您拥有的只是一个Object作为您的ItemBase。如果没有硬编码你的类型(即var item = new Item<ItemFile>();),你就永远不会知道更多 也就是说,使用这种方法,您可以非常清楚地使用Reflection迭代字段等。但这是此级别的运行时对象操作的限制。

答案 1 :(得分:1)

  

我希望能够使用不使用&lt;&gt;传递的类型从函数返回多种类型的类。

&LT;&GT; (泛型)是函数可以显式返回多个类型的机制。如果没有泛型,函数会返回它返回的任何类型。

object SomeFunction() // Returns an object

ItemBase SomeOtherFunction () // returns ItemBase

在上面的示例中,SomeFunction仍然可以返回任何类型(因为所有类型都继承自object。)但它不会是显式的。你所知道的只是它是object

同样,SomeOtherFunction可以返回ItemBase或任何继承自ItemBase的类。但你知道的就是这些。

理想情况下,您不希望函数返回一种类型(如objectItemBase),然后将函数的结果转换为另一种更具体的类型。该函数应该返回你想要的,你应该想要函数返回的内容。泛型有助于此。例如:

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

允许函数返回指定的类型,只要它是ItemBase或从一个继承。

这最后的评论似乎有点奇怪或无用,但这是事实。如果您发现自己处于上述规则不起作用的情况,并且您需要能够做一些您无法做或不应该做的事情,请回过头来重新考虑您为什么这样做。 ;试图这样做。这就是真正的问题所在。

这意味着你可能需要退一步,让自己摆脱你试图违背语言的情况。你想要完成什么?你怎么能用一种与语言相关的方式来实现它,而不是反对呢?