FreshMvvm icon indicating copy to clipboard operation
FreshMvvm copied to clipboard

multiple parameters for init method

Open EmilAlipiev opened this issue 8 years ago • 8 comments

Is it possible to have multiple parameters for init method when I need to pass more than 1. Of course I can create custom object with those parameters as property but this is kind of cumbersome. thanks :)

EmilAlipiev avatar Jul 26 '16 16:07 EmilAlipiev

I don't think a change is needed here.

It is not difficult to pass in params with object[].
This is much faster than creating an object with custom properties. Here's an example I just finished testing locally.

In the ICommand:

public ICommand AddContactCommand
{
    get {
        return new Command(async () => {
            // Initialize the array with three different classes.
            object[] threeBodyProblem = new object[] { _repository, Contacts[0], "string" };
            await CoreMethods.PushPageModel<ContactPageModel>(threeBodyProblem);
        });
    }
}

In the ContactPageModel's Init method:

public override void Init(object initData)
{
    var result = initData as object[];
    var indexZero = result[0] as Repository;
    var indexOne = result[1] as Contact;
    var indexTwo = result[2] as string;
}

I recommend offering this as a solution and not modifying the methods. Don't forget those null checks in real code =)

CarahBeck avatar Aug 29 '16 23:08 CarahBeck

Another alternative, that also might be nicer to use when C# 7 comes out (with the new Tuple deconstruction feature etc.).

CoreMethods.PushPageModel<SomeModel>(Tuple.Create(1, "a"));

public override void Init(object initData)
{
    var parameters = (Tuple<int, string>)initData;
}

Another way of getting multiple parameters, is to add a Init(params object[] parameters), and then you will have two Init methods. But I think the answer to @C0D3Name is better.

oddbear avatar Aug 31 '16 15:08 oddbear

There is also another alternative that might work. If the PushPageModel can take a Action<TViewModel>, then it should be possible to do something like:

CoreMethods.PushPageModel<SomeModel>((vm) => vm.Init("a", 1));

public override void Init(string a, int b) //Can however be called whatever you want.
{
    //
}

This should then be strongly typed and everything, as it don't depend on any baseclass.

oddbear avatar Sep 01 '16 08:09 oddbear

@oddbear tuple is a good way of resolving this issue but requires c#7. @C0D3Name I dont think this is a good solution. because in some cases I might need to pass over different types. I handle it as below. In this case your using Object will fail. many people dont like to work with Object type I believe.

if (initData is Customer) { }

EmilAlipiev avatar Jan 18 '17 16:01 EmilAlipiev

@EmilAlipiev It is possible to cast to another type from an object. This satisfies the test within your if statement. I have written a simple, 1-file console application to prove this point, it utilizes similar logic to your example if statement. Attached is the output from running the application.

`using System;

namespace ConsoleApplication1 {

public class Class1 {
	public string ClassName { get { return "Class1"; } }
}
public class Class2 {
	public string ClassName { get { return "Class2"; } }
}

class Program {
	static void Main(string[] args) {
		ClassTester(new Class1());
		ClassTester(new Class2());
		ClassTester(new object());

		Console.ReadKey();
	}

	private static void ClassTester(object theParameter) {
		if(theParameter as Class1 != null) {
			var classCast = theParameter as Class1;
			Console.WriteLine(classCast.ClassName);
		}
		else if(theParameter as Class2 != null) {
			var classCast = theParameter as Class2;
			Console.WriteLine(classCast.ClassName);
		}
		else {
			Console.WriteLine("Could not cast object to a known type.");
		}
	}
}

}`

classcastcapture

CarahBeck avatar Jan 18 '17 17:01 CarahBeck

Sorry about replying an old issue, but I do have a similar issue.

I wonder, is it possible to fetch some values from the previous PageModel? Or maybe I could just send the current instance of the PageModel to the next page, so I don't have to pack everything in an object and unpack in the new PageModel class. Any suggestion?

shawyunz avatar Dec 10 '19 21:12 shawyunz

Sounds like this would not scale easily.

One navigation to the page would probarbly work fine, but when you can access a page from 3-4 others (or 100)... then I would guess this to be really hard to maintain.

I am thinking the code inside the Init from just 4 diffrent previous pages would be something like:

switch(model)
{
    case model is AViewModel: /* DoSomething */ break;
    case model is BViewModel: /* DoSomething */ break;
    case model is CViewModel: /* DoSomething */ break;
    case model is DViewModel: /* DoSomething */ break;
}

However, the previous viewModel can have a common interface (or similar), to reuse the "fetch logic".

oddbear avatar Dec 11 '19 12:12 oddbear

Sounds like this would not scale easily.

Thanks for your reply. Or maybe send an instance of NextPageModel could be an alternative way. But by doing this, it actually moves the "init" stuff to a constructor. Is this feasible or is there any violation against the design of fresh MVVM? Cheers.

shawyunz avatar Dec 13 '19 00:12 shawyunz