leobelones
leobelones

Reputation: 598

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)?

Upvotes: 1

Views: 207

Answers (5)

Jamie Kelly
Jamie Kelly

Reputation: 309

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.

Upvotes: 1

Milcho
Milcho

Reputation: 339

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.

Upvotes: 0

Mikhail Vladimirov
Mikhail Vladimirov

Reputation: 13890

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.

Upvotes: 0

Soner Gönül
Soner Gönül

Reputation: 98740

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

Like;

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

Upvotes: 1

driis
driis

Reputation: 164281

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

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

Upvotes: 2

Related Questions