简体   繁体   中英

Get an instance of generic type

I have 2 Customer classes BusinessCustomer and NormalCustomer having individual properties and a Validate Method. From the implement class, based on some condition I might create Customer1 or Customer2. How can I create an instance of either BusinessCustomer or NormalCustomer based on T in Customer class so that I can call the validate method common to both the classes.

    public class Customer<T> where T : class
    {
        public T CustomerType;
        bool isValid;

        public Customer() //constructor
        {
            //for customer1, i want a new instance of BusinessCustomer 
            //for customer2, i want a new instance of NormalCustomer 
        }

        public bool Validate()
        {
            isValid = CustomerType.Validate();
        }
    }


public class BusinessCustomer
{
    public string CustomerHobby { get; set; }
    public bool Validate()
    {
        return true;
    }
}

public class NormalCustomer
{
    public string CustomerEducation { get; set; }
    public bool Validate()
    {
        return false;
    }
}

public class Implement
{
    public void ImplementCustomer()
    {
        var customer1 = new Customer<BusinessCustomer>();
        customer1.CustomerType = new BusinessCustomer {CustomerHobby="Singing"};
        customer1.Validate();

        var customer2 = new Customer<NormalCustomer>();
        customer2.CustomerType = new NormalCustomer { CustomerEducation = "High School" };
        customer2.Validate();

    }
}

Your first issue is with the following line:

isValid = CustomerType.Validate();

Since CustomerType is of type T , which can be any class , the compiler can't guarantee there's a Validate() method to be called. You'll need to fix this by creating a common interface. Let's call this ICustomer :

interface ICustomer
{
   bool Validate();
}

Now, both BusinessCustomer and NormalCustomer will need to implement said interface:

public class BusinessCustomer : ICustomer
{
   // Same code
}

public class NormalCustomer : ICustomer
{
   // Same code
}

Next, you'll have to change:

public class Customer<T> where T : class

To:

public class Customer<T> where T : ICustomer

Now, you'll only be able to create Customer<T> instances where T implements ICustomer , which will allow you to call the Validate method of CustomerType .

Next, if you wanted to new up a T in your constructor, you can do so like:

public Customer()
{
   CustomerType = new T();
}

But wait. What if T doesn't have a default public constructor, or is abstract? We'll also need to add this constraint to our generic type:

public class Customer<T> where T : class, new()

Now, new T(); works and you can only create instances of Customer<T> where T has a default constructor. You'll no longer have to set customer1.CustomerType if you don't want to.

Another quick note. Your method:

public bool Validate()
{
   isValid = CustomerType.Validate();
}

Either needs to return a bool (such as isValid ), or the signature needs to be void Validate() . Right now, you'll get a compiler error because not all code paths return a value.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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