简体   繁体   English

层次对象的通用类工厂或方法

[英]Generic class factory or method of hierarchy objects

I have hierarchy class and generic class:我有层次结构类和泛型类:

       public class Form
       {
           public string Name { get; set; }
           public string Producer { get; set; }
       }

       public class Book : Form
       {
           public string Topic { get; set; }
           public string Autor { get; set; }
       }

       public class Copybook : Form
       {
           public string Topic { get; set; }
           public int CountPages { get; set; }
       }

       public class Notebook : Form
       {
           public int Cost { get; set; }
       }

       public class Request<T> where T : Form
       {
           public T Form { get; set; }
       }

I want to make factory or method, which will create objects of generic class in depend of logic and params.我想制作工厂或方法,它将根据逻辑和参数创建通用类的对象。 How it make?它是如何制作的? I tried to do this, but the code did not work:我试图这样做,但代码不起作用:

        public enum FormParams
        {
            Book,
            Copybook,
            Notebook
        }

        public static class RequestFactory
        {
            public static Request<Form> Create(FormParams formParams)
            {
                if (formParams == FormParams.Book)
                {
                    return new Request<Book>();
                }

                if (formParams == FormParams.Copybook)
                {
                    return new Request<Copybook>();
                }

                return new Request<Notebook>();
            }
        }

If you think carefully, what you're asking for doesn't really make sense.如果你仔细想想,你所要求的并不真正有意义。 What if you did this?如果你这样做了怎么办?

var request = RequestFactory.Create(FormParams.CopyBook);
request.Form = new Book();

If the underlying type of request was Request<CopyBook> , then its Form property would have the type of CopyBook , and trying to set its value to a Book wouldn't make sense.如果request的基础类型是Request<CopyBook> ,那么它的Form属性将具有CopyBook的类型,并且尝试将其值设置为Book没有意义。

If you determine that the above use-case should never happen, you can formalize that fact by using an interface that doesn't allow the Form property to be set.如果您确定上述用例永远不会发生,您可以通过使用不允许设置Form属性的interface形式化该事实。 Then you can make that interface covariant .然后您可以使该接口covariant

public class Request<T> : IRequest<T>
    where T : Form
{
    public T Form { get; set; }
}

public interface IRequest<out T> where T : Form
{
    T Form { get; }
}

...
    public static IRequest<Form> Create(FormParams formParams)

But in that case you may find there's no reason to have IRequest be generic at all.但在这种情况下,您可能会发现根本没有理由让IRequest是通用的。

public class Request<T> : IRequest
    where T : Form
{
    public T Form { get; set; }

    Form IRequest.Form => this.Form;
}

public interface IRequest
{
    Form Form { get; }
}

...
    public static IRequest Create(FormParams formParams)

You need to add an Interface to your hierarchy so you can flag the generic parameter as covariant.您需要向层次结构添加一个接口,以便可以将通用参数标记为协变。

public class Request<T> : IRequest<T> where T : Form
{
    public T Form { get; set; }
}

public interface IRequest<out T> 
{
    public T Form
    {
        get;
    }
}

And then you need to change the return type of your Create method to an IRequest<Form> .然后您需要将Create方法的返回类型更改为IRequest<Form>

public static class RequestFactory
{
    public static IRequest<Form> Create(FormParams formParams)
    {

        if (formParams == FormParams.Book)
        {
            return new Request<Book>();
        }

        if (formParams == FormParams.Copybook)
        {
            return new Request<Copybook>();
        }

        return new Request<Notebook>();
    } 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM