dimanche 28 janvier 2018

Cast to a generic type

I have the following interfaces

public interface IMessageData {}

public interface IMessageSender<T> where T : class, IMessageData, new()
{
    Task<T> BuildType();
    Task SendMessage(T message);
}

and then a base implementation for the IMessageSender

public abstract class MessageSenderBase<T> : IMessageSender<T> where T : class, IMessageData, new()
{
    public MessageSenderBase() {
    }

    public abstract Task<T> BuildType();

    public async Task SendMessage(T message) {
        Console.WriteLine($"Sending {JsonConvert.SerializeObject(message)}");
        await Task.FromResult(0);
    }
}

To use these interfaces I usually create a new instance of a MessageData and create a specific implementation of MessageSenderBase like

public class MessageDataA : IMessageData {
    public MessageDataA() {
    }

    public string Description { get; set; }
}

and

public class ASender : MessageSenderBase<MessageDataA> {
    public override async Task<MessageDataA> BuildType() {
        MessageDataA result = new MessageDataA() { Description = "description" };
        return await Task.FromResult<MessageDataA>(result);
    }
}

At runtime I only have in configuration the names of the MessageSenderBase implementations and I need to create dynamically instances of these classes and invoke both methods. This is correctly achieved with this code:

var className = "ASender";
var buildMethodName = "BuildType";
var sendMethodName = "SendMessage";

Assembly assembly = Assembly.GetExecutingAssembly();
var type = assembly.GetType(className);
var instance = Activator.CreateInstance(type);

//invoke build method
var buildMethodInfo = type.GetMethod(buildMethodName);
dynamic buildAwaitable = buildMethodInfo.Invoke(instance, null);
var returnedType = await buildAwaitable;

//invoke send method
var sendMethodInfo = type.GetMethod(sendMethodName);
dynamic sendAwaitable = sendMethodInfo.Invoke(instance, new[] { returnedType });
await sendAwaitable;

My questions:

  1. can I cast the var instance = Activator.CreateInstance(type); to a stronger type instead of leaving it as var? This would avoid me to call methods by using MethodInfo and Invoke.
  2. As a further suggestion is there any way to make this design more strong typed?




Aucun commentaire:

Enregistrer un commentaire