0

For a given repository interface IRepository<T> where T: Base and a bunch of classes that inherit Base (for instance, Text) how do you create instances of a provider that implements IRepository, for instance JsonRepository<T> with Text as T (JsonRepository<Text>) and run methods on it?

I'd like to use reflection with a for or foreach to create instances of repositories for all the classes inheriting Base and perform some data management functions on them.

What I want to avoid - if you had 100 classes inheriting Base class you obviously wouldn't go creating instances manually in code and then running it?

mare
  • 13,033
  • 24
  • 102
  • 191
  • It sounds to me like you have completely the wrong idea here. Data management functions? That doesn't sound like OLTP me to me, which is really the only place that repositories are useful. If you're doing bulk data management or ETL, not so much. Don't let your abstractions pin you down into only one way of looking at a problem. – jason May 14 '12 at 17:50
  • I am fuzzy on what you are asking here. Are you saying you already have 100 classes that inherit Base and you want get instances of those classes via reflection so you don't have to hard code the 100 class names? – Katie Kilian May 14 '12 at 17:55

3 Answers3

0

You can use Activator.CreateInstance

See an example here:

Modified to your example:

var d1 = typeof(JsonRepository<>);
Type[] typeArgs = { typeof(Text) };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
Community
  • 1
  • 1
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
  • Why do you assume the constructor is parameterless? – jason May 14 '12 at 17:58
  • Because most data sources have a connection string or a path to file or some indication where the source is. – jason May 14 '12 at 18:05
  • this looks promising but still requires hand coding typeof(Text)...preferably I'd like to have a foreach that would enumerate those types that inherit Base – mare May 14 '12 at 18:12
  • Yes, you would need to create a loop and just use the types of all `Base` types you want to create. Let me see if I can find an example – SwDevMan81 May 14 '12 at 18:16
  • This question could help [Getting all types that implement an interface](http://stackoverflow.com/q/26733/95573). Then just loop through the types and use the type instead of `typeof(Text)` – SwDevMan81 May 14 '12 at 18:17
  • @SwDevMan81: I'm not assuming anything. It could go either way. You didn't even address that possibility at all. – jason May 14 '12 at 20:06
  • @SwDevMan81 you pointed me into the right direction and i'm posting my code that I got out from all of this as my own answer below but accepting yours. – mare May 14 '12 at 21:36
0

With @SwDevMan81's help and some reflection I managed to hack together this and it actually works perfectly:

var type = typeof(Base);
var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
        .SelectMany(s => s.GetTypes())
        .Where(p => type.IsAssignableFrom(p));

var jsonProviderClass = typeof(JsonContentProvider<>);
var xmlProviderClass = typeof(XmlContentProvider<>);

    foreach (var t in types) {
        Type[] typeArgs = { t };
        // get XML provider
        var xmlGenericProvider = xmlProviderClass.MakeGenericType(typeArgs);
        object xmlProvider = Activator.CreateInstance(xmlGenericProvider);
        // get JSON provider
        var jsonGenericProvider = jsonProviderClass.MakeGenericType(typeArgs);
        object jsonProvider = Activator.CreateInstance(jsonGenericProvider);
        // methods to run
        MethodInfo xmlMethod = xmlGenericProvider.GetMethod("GetContent", new Type[] { typeof(string) });
        MethodInfo jsonMethod = jsonGenericProvider.GetMethod("Update");
        // get content from XML provider
        var result = xmlMethod.Invoke(xmlProvider, new object[] { string.Empty });
        // enumerate XML content items
        foreach (var item in ((IEnumerable)result)) {
            // update them via JSON provider
            object[] parametersArray = new object[] { item };
            var update = jsonMethod.Invoke(jsonProvider, parametersArray);
        }
    }
mare
  • 13,033
  • 24
  • 102
  • 191
-1

You currently use a generic constraint but why not use the 'new' constraint which denotes the generic type has a public parameterless ctor i.e.

IRepository<T> where T: Base, new

Which would then mean you could call:

abstract class ctor()
{
    IRepository rep = new T();
}

Now how you apply this may be through a base abstract class or you could simply return the rep instance by means of a propfull... It's upto you.

I have to admit your question is a little fuzzy so please excuse if this is not what you are getting at.

Paul Sullivan
  • 2,865
  • 2
  • 19
  • 25