How can I get implicit type conversions from strin

2019-08-15 17:55发布

问题:

I have the following in my model:

public sealed class OAuthProvider
{
    private readonly string name;

    private const string SOME_PROVIDER = "SOMEPROVIDER";
    public static readonly OAuthProvider SomeProvider = new OAuthProvider(SOME_PROVIDER);

    private OAuthProvider(String name) { this.name = name; }
    public override String ToString(){ return name; }
    public static implicit operator string(OAuthProvider oAuthProvider)
    {
        return oAuthProvider.name;
    }
    public static implicit operator OAuthProvider(string oAuthProvider)
    {
        switch (oAuthProvider)
        {
            case SOME_PROVIDER : return SomeProvider ;
            default: return null;
        }
    }
}

And this in my OAuth controller:

public ActionResult Profile(OAuthProvider network)
{...}

And this in my view:

@model SomeModel
Html.RenderAction("Profile", "OAuth", new { network = Model.Network });

Where Model.Network is a string

When this view is rendered, I can see (via breakpoint) that Model.Network is coming in as a string that isn't null. My Profile(OAuthProvider) is being called but network is coming in as null despite the implicit type conversion being in place.

Am I going about this the wrong way? Am I forced to do an explicit cast?

回答1:

Not sure if this might work, it's not a direct answer to what you have (but it's hard to say w/o debugging in similar cases) but might help (and is much text for the comment)...

in similar cases when the binding doesn't work as expected, often helps to debug - and that by making a custom binder.

In your Application_Start you do something like this...

ModelBinders.Binders.Add(typeof(YourNamespace.OAuthProvider), new YourNamespace.Binders.OAuthProviderClassBinder());

(you can similarly do for the controller if it never reaches the action or other cases e.g. ControllerBuilder.Current.SetControllerFactory(new RedirectControllerFactory()); where factory derives from DefaultControllerFactory similar to below example)

...then in the code somewhere you define the binder like this, simplified...

public class OAuthProviderClassBinder : DefaultModelBinder
{
    //public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    //{
    //}
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var model = (OAuthProvider)base.CreateModel(controllerContext, bindingContext, modelType);

        // ...you change, inspect set etc.

        return model;
    }
}

...this is the way to custom bind, adjust your 'passing' values - also check if problems with them etc.
And you might be better off overriding the other methods, e.g. BindModel

Here are a link fast...
Creating a custom model binder
http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultmodelbinder.aspx