简体   繁体   中英

Casting Object depending on its type

I made a validation method for business rules that are not verified from my rules in the model, but I'm having a problem to make it work. Since there are two possible scenarios(customer or seller registration), they need to be treated separately in their own views and models. The seller registration inherits from customer registration for the basic info, so all fields in customer are also in seller. But since I'm working with 2 different models, even though both have the same fields that I'm doing the validation upon, I needed to use Object to use the same validation method. But unfortunately I'm having trouble to do so.

[CustomHandleError]
private bool ValidateRegistrationForm (Object registerViewModelObject) {
    if (registerViewModelObject is RegisterViewModel)
    {
        RegisterViewModel registerViewModel = 
            (RegisterViewModel)registerViewModelObject;
    }
    else
    {
        RegisterSellerViewModel registerViewModel = 
            (RegisterSellerViewModel)registerViewModelObject;
    }

    if (ModelState.IsValid)
    {
        string [] names = registerViewModel.Name.Split (
            new string [] {" "}, StringSplitOptions.RemoveEmptyEntries);
        if (names.Length == 1)
            ModelState.AddModelError ("Name", "Fill your full name");

        if (CustomerUtilities.IsCpf (registerViewModel.Identity) == false)
            ModelState.AddModelError ("Identity", "Invalid CPF value");

        if (this.AuthenticatorService.IsExistentUser (registerViewModel.Email))
            ModelState.AddModelError ("Email", "Email already registered");
    }
}

As you can see, after the if (ModelState.IsValid) the IntelliSense doesn't find registerViewModel in the current context. I wonder why this happens, since that variable is defined inside the if AND the else above, so there is no way to reach that code without it being defined.

Is there any workaround for this(other than creating a new method or passing 2 variables)?

Declare RegisterViewModel outside of the if block scope, and assign it within the if block.

RegisterViewModel registerViewModel;
if (registerViewModelObject is RegisterViewMOdel)
{
     registerViewModel = // ...
}
else
{
     registerViewModel = // ...
}

You should define RegisterViewModel outside from your if statemtent. And make assignment inside your if statement.

Like;

RegisterViewModel registerViewModel;
if(...)
{
  //make your assigment here.
}

If you wish to have two separate variables then declare both outside of the if statement and test for null after.

RegisterViewModel registerViewModel;
RegisterSellerViewModel sellerModel; 

if (registerViewModelObject is RegisterViewModel)
{
    registerViewModel = (RegisterViewModel)registerViewModelObject;
}
else
{
    sellerViewModel = (RegisterSellerViewModel)registerViewModelObject;
}

However, defining an interface to use instead of Object would be the better option.

public interface IRegisterViewModel
{
    public string Name { get; set;}
    public ... Identity {get; set;}
    ...
}

public class RegisterViewModel : IRegisterViewModel
{
    ...
}

public class RegisterSellerViewModel : IRegisterViewModel
{
    ...
}

Then use ValidateRegistrationForm(IRegisterViewModel registerViewModel) and you can get rid of the if statement entirely.

You probably need to extract methods that are common for RegisterViewModel and RegisterSellerViewModel into an interface and implement it in both classes. Then cast registerViewModelObject to this interface regardless of its actual type.

The problem occurs since you don't have a single variable defined in the main scope of the function. In the way that you have written your code, you define two variables that are inside different scopes.

How I would go about with the solution:

I would make a base class.

class RegisterModel
{
   public string Name;
   public IdentifyType Identify;
   public string Email;
}

And then both your classes can inherit from the base class. Like this:

class RegisterViewModel
   : RegisterModel
{...}
class RegisterSellerViewModel
   : RegisterModel
{...}

Now you can actually covert the Object variable in your function a single time. Like this:

private bool Validate(Object viewModel)
{
   var castViewModel = (RegisterModel)viewModel;
   if(ModelState.IsValid)
   {
      ...
   }
}

Note that this will cause a run-time error if viewModel is not of type RegisterModel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM