Tracey23
Tracey23

Reputation: 23

Need help correcting reflection

The following program works only with the classes which are located within the main project. Would you be so kind to advise or correct the code so that it becomes possible to use the classes from other projects. I added reference of the ClassLibrary1 project to the Example01 project.

The desired project

The error which I am getting is

Unhandled Exception: System.ArgumentNullException: Value cannot be null.
Parameter name: type
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at Example01.Program.InstantiateObject(String assemblyName, String fullName) in c:\Projects\Example01\Example01\Program.cs:line 59
    object obj = Activator.CreateInstance(objectToInstantiate);
   at Example01.Program.RandomizeList[TClass](Int32 count, String assemblyName) in c:\Projects\Example01\Example01\Program.cs:line 34
    randomizedList.Add(
   at Example01.Program.Main(String[] args) in c:\Projects\Example01\Example01\Program.cs:line 18
    List<Class02> randomizedList03 = RandomizeList<Class02>();

Here is my code with the reference what works and what fails:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ClassLibrary1.Classes;

namespace Example01
{
    class Program
    {
        static void Main(string[] args)
        {
            // This works
            List<Class01> randomizedList01 = RandomizeList<Class01>();
            // This works
            List<Test01> randomizedList02 = RandomizeList<Test01>();
            // This fails
            List<Class02> randomizedList03 = RandomizeList<Class02>();

            Console.ReadKey();
        }


        private static List<TClass> RandomizeList<TClass>(int count = 10, string assemblyName = "")
        {
            if (assemblyName.Length == 0)
                assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
            var listOfSubClasses = SubClasses<TClass>();
            var randomizedList = new List<TClass>();
            var rand = new Random();
            count = 10;

            for (int i = 0; i < count; i++)
                randomizedList.Add(
                    (TClass)
                        InstantiateObject(assemblyName,
                        listOfSubClasses.ElementAt(rand.Next(listOfSubClasses.Count()))
                        .FullName));
            return new List<TClass>(randomizedList as IEnumerable<TClass>);
        }

        // Enumerate all subclasses for the specified class
        public static IEnumerable<Type> SubClasses<TClass>()
        {
            var subclasses =
                (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                 from type in assembly.GetTypes()
                 where type.IsSubclassOf(typeof(TClass))
                 select type).ToList();
            return subclasses;
        }

        private static object InstantiateObject(string assemblyName, string fullName)
        {
            Assembly аsm = Assembly.Load(assemblyName);
            // Get the assembly metadata
            Type objectToInstantiate = аsm.GetType(fullName);
            // Create object on the fly
            object obj = Activator.CreateInstance(objectToInstantiate);
            return obj;
        }
    }

    #region Sample Classes
    public class Class01
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class SubClass0101 : Class01
    {
        public int Length { get; set; }
    }

    public class SubClass0102 : Class01
    {
        public int Length { get; set; }
    }

    public class SubClass0103 : Class01
    {
        public int Length { get; set; }
    }
    #endregion
}

Many thanks in advance!!!

Upvotes: 0

Views: 90

Answers (1)

toadflakz
toadflakz

Reputation: 7942

Your problem is this line:

assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name

You need to enumerate all the referenced assemblies, not just the current executing assembly, so probably need to use GetReferencedAssemblies() on the result of GetExecutingAssembly() as your main project is the executing assembly and your referenced project would be a referenced assembly.

Upvotes: 1

Related Questions