Cast interface to a class?

2019-08-20 18:45发布

问题:

I have a cms with a page that contains forms.

I want in the cms to have a dropdown with different class names that all implement a validation interface.

My form handlers contain a process method which I want to validate against the selected validation class.

So I have this interface:

public interface IEligibilityValidation
{
    bool IsValid();
}

and for example this class

public class ComplexEligibilityValidation : IEligibilityValidation
{
    public bool IsValid()
    {
        return true; /* complex logic here */
    }
}

public class SimpleEligibilityValidation : IEligibilityValidation
{
    public bool IsValid()
    {
        return true; /* less complex logic here */
    }
}

And then I have the form handler that can read the selected class name for the validation.

I am unsure whether my handler should implement IEligibilityValidation as well or whether I can somehow invoke the class using reflection.

For example:

public class SampleFormHandler : IEligibilityValidation
{
    public SimpleFormHandler(FormViewModel model, INode node)
    {
        this.model = model;
        this.node = node;

        eligiblityValidationClass = GetPropertyValue("eligibilityValidation");

    }

    public SampleProcessResult Process()
    {
            if (!string.IsNullOrEmpty(eligiblityValidationClass))
            {
                var thisType = Type.GetType(eligiblityValidationClass);
                var thisInstance = Activator.CreateInstance(thisType);
                var isValid = ((IEligibilityValidation)thisInstance).IsValid();
                /* Works however, I need the IsValid to have access to a the FormHandler's properties and injected services */
            }

    }

    public bool IsValid()
    {
        /* Will Always be ignored */
        return true;
    }
}

What is the most elegant way for doing something like this?

The idea is that different FormHandlers will have a different Validation class assigned to them and when invoked the IsValid method will be able to use the properties of that form.

I am looking for some advanced architecture or something smarter than just require unnecessary code.

Thanks

回答1:

SampleFormHandler shouldn't implement the interface. If I'm understanding your design correctly, you need to create an instance of the dynamically determined type, and then cast the object to the IEligibilityValidation interface.

public SampleProcessResult Process()
{
    if (eligiblityValidationClass != Guid.Empty)
    {
        Type validatorType = Type.GetTypeFromCLSID(eligiblityValidationClass);
        IEligibilityValidation validator;
        try
        {
            validator = Activator.CreateInstance(validatorType) as IEligibilityValidation;
        }
        catch (COMException)
        {
            // The class doesn't exist, or instance failed to be created
            // for some other reason.
        }

        if (validator == null)
        {
            // The class exists, but it doesn't implement the interface.
        }

        bool isValid = validator.IsValid();
    }
}


回答2:

have you heard about cast (as, is)? Casting and Type Conversions (C# Programming Guide)

And you class SampleFormHandler hasn't implementation of IEligibilityValidation

anyway ((IEligibilityValidation)this).IsValid() you solution

UPDATE:

So you have to create instance of type that you want to execute IsValid on. So

var desiredInstance = Activator.CreateInstance(desiredType);
var validationDesired = desiredInstance as IEligibilityValidation;
if(validationDesired  != null){
validationDesired.IsValid();
}