简体   繁体   中英

C# Using Activator.CreateInstance factory pattern how to

I have user class say, User

public class User
{
public int Id {get;set;}   
public string Name {get;set;}

}

and an interface which returns a group of users by looking at the given user's Id

public intervace IPeople
{
   IList<User> GetPeople (int id);
   string Key {get;}
}

Here are few implementations of IPeople

public class Friends : IPeople
{
   public IList<User> GetPeople (int id)
   {
      return ListOfUsersWhoAreFriends();
   }

    public string Key {get { return "Friends"; }
}


public class Fans : IPeople
{
   public IList<User> GetPeople (int id)
   {
      return ListOfFans();
   }
   public string Key {get { return "Fans"; }

}

Now in my calling method

 string key="SomeKey" ; //It could be friends or fans
 int id =1;
 IPeople[] allPeople = GetAllInstancesOf<IPeople>();

 IList<User> requiredUsers = allPeople.FirstOrDefault(m=>m.Key == key).GetPeople(id);

So to say, I create instances of all the derived classes and then check which one I need, before I call the function on it. Its working fine, but I feel, from performance point of view, its not a very good solution, as I create instance by reflection. What is the better way to achieve it. Some factory method If yes, how ??

Help will be appreciated.

Regards

Parminder

I am guessing you are using reflection in your GetAllInstancesOf class? Not sure where you are populating your list of People from or why you need a key and an Id, but for a factory pattern in this instance, I would use the following

public IList<User> UserFactory(string kindOfPeople)
{
  switch (kindOfPeople.ToLower())
  {
    case "fans":
      return ListOfFans();
    case "friends":
      return ListOfUsersWhoAreFriends();
    default:
      return new List<User>();
  }
}

If the kinds of people (fans, friends, family etc.) is limited and doesn't change very often in your application, then I would make it an enum and pass that into the factory

public enum KindsOfPeople { Friends = 0, Fans = 1}

PS: This assumes that both Fans and Friends derive from the User class. This wasn't shown in your code. A nice way of using the factory pattern is if all the possible classes that are returned from the factory inherit from a common base class.

I feel, I found a better solution. Here it goes.

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public interface IPeople
{
    IList<User> GetPeople(int id);

}


public class Friends : IPeople
{
    public IList<User> GetPeople(int id)
    {
        return new List<User>();
    }



    public class Fans : IPeople
    {
        public IList<User> GetPeople(int id)
        {
            return new List<User>();
        }
    }


    public class Program
    {
        static void Main(string[] args)
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<Friends>().Named<IPeople>("Friends");
            builder.RegisterType<Fans>().Named<IPeople>("Fans");

            IContainer c = builder.Build();

            var x = c.ResolveNamed<IPeople>("Friends");

        }
    }
}

As I am using Autofac, I looks after the register with named keys.

Thanks

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