I know this question may be nonsense, but I've been thinking about it for some time. I am developing a Xamarin Forms app that works both on Windows and on Android, and they share most of the code. However, there is a particular page that, for some reasons needs to be platform specific (because of the UI elements distribution that makes the app look weird). As the number of lines of code increases, and them being almost the same, I came up with the idea of creating a separate script that handles the logic for both pages, and I would simply have to call these new methods from each page. the problem comes here, as I want to modify some UI elements (I've previously created some getters for each UI element), and as each page has a different class name, let's say Page1 and Page2, is there any way that I could set in run time, depending on the platform on which the app is running, a generic variable that can take either Page1 or Page2 type?
What I tried
I have tried with Shared Projects and compilation directives
#if WINDOWS_UWP
...
#elif ANDROID
...
#endif
but I don't know if it is me that I don't know how to use it properly, or if it doesn't work at all. At compilation time, it says that this generic variable does not have a definition for whatever variable belonging to the Page1 and Page2 classes.
My aim is to have something like this
class Page1{
int SameVariableName;
}
class Page2{
int SameVariableName
}
class GenericClass{
//Check if Platform is Windows or Android
if (Windows) { Page1 pageVariable = new Page1();}
else if (Android) { Page2 pageVariable = new Page2();}
pageVariable.SameVariableName = (...);
}
The problem is that, as the pageVariable assignment is not done until runtime, it gives plenty of compilaiton errors such as pageVariable does not contain a definition for SameVariableName
Many thanks in advance for reading this and trying to help me
CodePudding user response:
It looks like you should have done this the other way around. Since most of the code is exactly the same, there should be a Page class.
Then, you could actually convert Page1 or Page2 into a Page class, so that your generic class handles only a Page class and don't have to deal with Page1 or Page2. You proceed with the code and then if you need to send them back, convert to other way around.
But honestly, the reel way to do what you are trying to do is learning and using C# interface, using interface you could make a parent class that strategicallly handles both children classes and the problem would have been solved even before being an actual problem. You would have a Page class and both Page1 and Page2 would inherit from the Page class. Your compiler will not complain this way.
CodePudding user response:
If you have shared code, have Page1 and Page2 inherit
from a BasePage class.
The differences are done by defining abstract
(or virtual
, if you need a "base" definition) methods and properties, and implementing those in both Page1 and Page2.
public abstract class BasePage
{
abstract SomeType SomePropertyB { get; set; }
abstract void SomeMethodA();
public void SomeMethodC()
{
// These access values/code that are different, depending on which Page we are in.
var b = SomePropertyB;
SomeMethodA();
}
public class Page1 : BasePage
{
override SomeType SomePropertyB
{
get => ...;
set => ...;
}
override void SomeMethodA()
{
...
}
// Putting a page into a variable that could be either page.
BasePage page = new Page1();
If there were no shared implementation code, BasePage could be an interface
instead.
By convention, some name starting with I
:
public interface IPage
{
SomeType SomePropertyB { get; set; }
void SomeMethodA();
}
public class Page1 : IPage
{
public SomeType SomePropertyB
{
get => ...;
set => ...;
}
public void SomeMethodA()
{
...
}
// Putting a page into a variable that could be either page.
IPage page = new Page1();