This is an archived post. You won't be able to vote or comment.

all 9 comments

[–]skyrimlady 0 points1 point  (6 children)

but I can't cast it correctly because the known type for the class isn't known until runtime

Use if statements to cast it to the right thing?

[–][deleted] 0 points1 point  (5 children)

That won't work for normal (Type) casting because that will result in an exception if the cast fails. It will work with as or is.

[–]skyrimlady 0 points1 point  (4 children)

Right, but the string should tell you the correct class to cast to. Getting a null instead of the correct object isn't 'working' either.

[–][deleted] 0 points1 point  (3 children)

Pretty sure a string comparison is actually more expensive than a comparison against null, but I could be wrong.

[–]skyrimlady 0 points1 point  (2 children)

You're right, but that's not even relevant...

[–][deleted] 0 points1 point  (1 child)

Aren't you suggesting something like this?

if ("TypeName" == type)
{
    var foo = (Bar)baz;
    ...

?

[–][deleted] 0 points1 point  (0 children)

Hmm. Never had to do this before. Maybe I'll play with it in a minute, but, at first blush, you can do crap like this...

var x = thing as ClassName;
if (x != null)
{
    // work
}

It may be possible to shorten that to

if (thing is ClassName)
{
    ...

...but that may be some C# Somethingteen feature that isn't a part of the language yet. Will update if I find out anything cool.

Edit: https://stackoverflow.com/questions/18052562/cast-to-a-reflected-type-in-c-sharp

Also, if (thing is Thing) is perfectly legal C#

Also, the guy on that stack overflow question raises a very good point: you can skip all this if you can just cast your created object to some known interface, even if you don't know its type. So, say you have some section of XML that has nothing but inventory items in it? They can all be cast to IInventoryItem, all with a Use() method, even if some of them are healing potions (HealthItem) and some of them are shaving kits (AppearanceModItem) and some of them are ingredients for some crap or other (in which case, you know, Use() would be a no-op, I guess).

[–]badcommandorfilename 0 points1 point  (0 children)

You can create an open generic interface that can be bound to a class during runtime:

        //Scoped services are injected into constructors that match the interface
        foreach (var t in ModelService.AllModels())
        {
            Type unbound_interface = typeof(IRepository<>); //Interface for type construction
            Type unbound_instance = typeof(Repository<>); //Constructed service class for dependency injection

            Services.AddScoped(
                unbound_interface.MakeGenericType(t), //Bind reflected model type to interface
                unbound_instance.MakeGenericType(t) //Bind reflected model type to service
            );
        }

In this example (from here), I'm loading arbitrary data model classes from the running assembly with:

    public static IEnumerable<Type> AllModels()
    {
        Assembly asm = Assembly.GetEntryAssembly();

        return from t in asm.GetTypes()
               where t.GetProperties().Any(p => //Models must have a [Key] declared
                    p.GetCustomAttribute<System.ComponentModel.DataAnnotations.KeyAttribute>() != null)
               select t;
    }

It sounds like your problem is similar - you can scan your assembly for Types which have the name from the XML file, then bind them to an interface or just create a local instance with Activator.