I am developing Xamarin Forms cross platform Application with Prism.Forms.
Trying to implement modularity in my app using Prism.Modularity.
I have created couple of modules (xamarin forms portable class libraries) in addition to the existing default portable class library. Now I have to use the global static variables that i have declared in App.Xaml.cs (In APP class) in the module. Is there anyway i can access current App in module? Or is there any alternative to share data between modules and the main App.
Like shared services?
Declare an interface somewhere reachable by all modules that need it, and register an implementation singleton in one of the modules...
Example:
public interface ISomeDataProvider
{
int SomeNumber { get; set; }
}
internal class SimpleDataProvider : ISomeDataProvider
{
public int SomeNumber { get; set; }
}
internal class InAModule
{
public InAModule( ISomeDataProvider dataProvider )
{
dataProvider.SomeNumber = 1;
}
}
internal class InAnotherModule
{
public InAnotherModule( ISomeDataProvider dataProvider )
{
_dataProvider = dataProvider;
}
public void PrintSomeNumber()
{
Console.WriteLine( _dataProvider.SomeNumber.ToString() );
}
private readonly ISomeDataProvider _dataProvider;
}
Related
I have a class containing constants:
namespace Test.AppService
{
public static class Const
{
public const bool Tmr = false;
public const int Pti = 10;
...
I was wondering if this would be a good candidate for dependency injection or would it be better to leave it as it is and just add using for Test.AppService into every page? Would appreciate advice on this.
Reading your comment about needing to use a different set of constants if that is something you see happening then Dependency injection makes sense. For example if you are using different environments like DEV, QA, Release comes to mind.
You would need to declare an interface with all your public fields. Implement that Interface in different classes with all the possible different scenarios. Then you can register your interface and the class with your desired set of values that you would be able to swap as needed.
For example:
public interface IConfiguration
{
public string ConnectionString {get;}
}
public class QaValues : IConfiguration
{
public string ConnectionString
{ get
{
return "qaconnection";
}
}
}
public class ReleaseValues : IConfiguration
{
public string ConnectionString
{ get
{
return "releaseconnection";
}
}
}
DependencyService.Register<IConfiguration,QaValues>();
I have an application that uses a static class to store settings:
namespace ABC
{
public static class MS
{
public static bool abc;
public static bool def;
...
}
}
When the app starts up it goes to the database and updates some of these settings.
I have been told that holding them in a static class is not ideal for when I am doing bindings and adding notification so I'm thinking I should new a class and the hold them in an instance. If that's the case can someone give me some advice. Should I do that when the application starts up and should it be in the constructor of the App() if that is the best way to do it then how can I do this. Any small 4-5 line example would be a big help
public partial class App : Application
{
public static xxx
public App()
{
AS.appUpdated = "Feb 1, 2017";
AS.appVersion = "0.1";
InitializeComponent();
MainPage = new MS.MainPage();
}
}
Have a look at James Montemagno's settings plugin.
https://github.com/jamesmontemagno/SettingsPlugin
This abstracts away a lot of the plumbing around settings and persisting them locally. Calling one of your settings from anywhere in your application then becomes as simple as calling Settings.MySettingName.
When it comes to binding these values to a view I would always create a property for them in your view model that simply returns the value from the settings. If need be you can put them in a base viewmodel and go from there.
public class MyViewModel : BaseViewModel
{
}
public class BaseViewModel
{
public bool SettingA => Settings.SettingA;
public bool SettingB => Settings.SettingB;
}
I'm developping a MEF-based plugin system, in which every dll file under ~/WebPlugins/ folder which exports interface IPluginInfo is considered as a plugin.
public interface IPluginInfo
{
string Name { get; }
string Description { get; }
string AssemblyName { get; }
string Version { get; }
PluginType PluginType { get; }
Guid PluginGuid { get; }
}
Besides interface export, every dll exports it's own controllers like this:
namespace WebSettings.Controllers
{
[Export("Groups", typeof(ARMController))]
[PartCreationPolicy(CreationPolicy.NonShared)]
[ArmAuthorize(Roles = "WebSettings")]
public class GroupsController : ARMController
....
In main project i have an overrided DefaultControllerFactory's CreateController method, which allows to search for needed controllers among MEF exported.
public class ARMControllerFactory : DefaultControllerFactory
{
public override IController CreateController(RequestContext requestContext, string controllerName)
{
IController controller = null;
try { controller = base.CreateController(requestContext, controllerName); } catch { }
if (controller == null) controller = PluginManager.GetInstance<ARMController>(controllerName);
if (controller == null) throw new Exception("Controller not found!");
return controller;
}
}
Also, there is an overrided RazorViewEngine view location search paths. It allows MVC to search for views in ~/WebPlugins/Views/ folder.
So, everything seems to be Okay, but no.
It is normal practice when controller-view pair uses some model class to pass data between them. But in case of MEF controller export MVC can't find model class, which located in same dll from which controller is exported. And, of cource, view compilation fails on that stage and MVC returns an YSOD in which it complains that can't find model's namespace.
The first idea was to export model classes too, but I can't find out what to do with that exports.
How to tell MVC to use it?
Is there a known workaround for this problem?
I'm mucking about with reactive extensions and Iv'e hit a snag that I can't for the life of me work out what the cause is.
If I use a .NET 4 console mode app, where everything is static as follows:
using System;
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private static readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
static void Main()
{
_subject.Subscribe(RespondToNewData);
}
private static void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
DaftFrog is just a test class in my fake DAL class, this is a simple .NET 4 Class library project, the DaftFrog class, is a simple poco with a few fields in, the dal.save method just simply does a console.WriteLine of a field in the DaftFrog object.
Both classes are just simple stand in's for the real things once I get around to making the RX code work.
Anyway, back to the problem, so the code above works fine, and if I do a few
_subject.OnNext(new DaftFrog());
calls, the fake dal class, prints out what I expect and everything works fine...
HOWEVER>....
If I then transport this code as is, to a class library, and then new up that class library from within my "static program" as follows:
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
namespace RxProducer
{
public class Producer
{
private readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
private int _clock;
public void Start()
{
_subject.Subscribe(RespondToNewData);
}
public void Stop()
{
}
public void Tick()
{
if(_clock % 5 == 0)
{
DaftFrog data = new DaftFrog();
_subject.OnNext(data);
}
_clock++;
}
private void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
And then use that class in my program
using System;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Producer _myProducer = new Producer();
static void Main()
{
_myProducer.Start();
while(!line.Contains("quit"))
{
_myProducer.Tick();
line = Console.ReadLine();
}
_myProducer.Stop();
}
}
}
Then my project fails to compile.
Specifically it fails on the line:
_subject.Subscribe(RespondToNewData);
in the RxProducer class library, mores the point, the error the compiler throws back makes little sense either:
Error 1 The best overloaded method match for 'System.Reactive.Subjects.Subject<FakeDal.Entites.DaftFrog>.Subscribe(System.IObserver<FakeDal.Entites.DaftFrog>)' has some invalid arguments H:\programming\rxtesting\RxProducer\Producer.cs 17 7 RxProducer
Error 2 Argument 1: cannot convert from 'method group' to 'System.IObserver<FakeDal.Entites.DaftFrog>' H:\programming\rxtesting\RxProducer\Producer.cs 17 26 RxProducer
At first I thought that it might have been the static thing, so I made everything in the class library static, and that made no difference at all.
Iv'e really not done much with Rx until now, but I work with C# and VS 99% of the time, so I'm aware that the error is telling me it can't convert a type of some description, I just don't understand why it's telling me that, esp when the code works perfectly in the static program, but not in a class library.
Shawty
UPDATE
Second thoughts, I just know there are going to be those who insist that I post the fakedal and daft frog definitions, even though IMHO they won't be required, but to pacify the hordes of pretenders who will ask here they are :-)
using System;
namespace FakeDal
{
public class Repository<T>
{
public void Save(T entity)
{
Console.WriteLine("Here we write T to the database....");
}
}
}
namespace FakeDal.Entites
{
public class DaftFrog
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsTotalyDaft { get; set; }
}
}
Include using System; into file where you have Producer, this will help to convert RespondToNewData to IObserver<T>.
Sounds like the compiler is having trouble inferring the Action...might be missing a using statement for the relevant extension method. Alternatively, try either of:
_subject.Subscribe ((Action<DaftFrog>) RespondToData);
Or:
var obs = Observer.Create ( I forget the overload );
_subject.Subscribe( obs);
Below, I have code for an object that I would like to test. It is in an assembly called Business and I have added the attributes in the AssemblyInfo.cs to make internals visible to the test and rhino mocks which are located in another assembly. When testing the GenerateReport method, I can not fake out the call to ValidateWorkingDirectory when it is "internal" (System.ApplicationException : Must set Working Directory before any method calls.). If I make ValidateWorkingDirectory public, the problem goes away. I thought InternalsVisibleTo would address this issue.
public class MyClass : IMyClass
{
private readonly IMyClassDataProvider _myClassDataProvider;
public virtual string WorkingDirectory { get; set; }
public MyClass(IMyClassDataProvider myClassDataProvider)
{
_myClassDataProvider = myClassDataProvider;
}
internal virtual void ValidateWorkingDirectory()
{
if (string.IsNullOrEmpty(WorkingDirectory))
{
throw new ApplicationException("Must set Working Directory before any method calls.");
}
}
public virtual void GenerateReport(vars)
{
ValidateWorkingDirectory();
InsertData(_myClassDataProvider.GetData(vars), "ReportName");
}
internal virtual void InsertData(DataSet analysis, string fileName)
{
DoSomeStuff();
}
private static void DoSomeStuff()
{
//Whatevs
}
}
//In AssmeblyInfo.cs
[assembly: InternalsVisibleTo("UnitTests.Business")]
[assembly: InternalsVisibleTo("Rhino.Mocks")]
[TestFixture]
public class MyClassTests : TestFixtureBase
{
private MockRepository _mocks;
private IMyClassDataProvider _myClassDataProvider;
private MyClass _myClass;
private var _vars;
[SetUp]
protected void Init()
{
_mocks = new MockRepository();
_myClassDataProvider = _mocks.StrictMock<IMyClassDataProvider >();
_myClass = _mocks.PartialMock<MyClass>(_myClassDataProvider);
_vars = "who cares";
}
[Test]
[ExpectedException(typeof(ApplicationException), ExpectedMessage = "Must set Working Directory before any method calls.")]
public virtual void ShouldThrowAnExceptionIfWorkingDirectoryNotSet()
{
Expect.Call(_myClass.WorkingDirectory).Return(Random.Get<bool>() ? null : string.Empty);
_mocks.ReplayAll();
_myClass.ValidateWorkingDirectory();
_mocks.VerifyAll();
}
[Test]
public virtual void ShouldGenerateReport()
{
DataSet dataSetToReturn = new DataSet();
using (_mocks.Ordered())
{
Expect.Call(() => _myClass.ValidateWorkingDirectory());
Expect.Call(_myClassDataProvider.GetData(vars)).Return(dataSetToReturn);
_myClass.InsertData(dataSetToReturn, "ReportName");
}
_mocks.ReplayAll();
_myClass.GenerateReport(vars);
_mocks.VerifyAll();
}
}
You need to expose your internal members to proxy assembly, not Rhino's assembly itself:
[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]
When a class is mocked, a new class is generated at run-time which is derived from the mocked class. This generated class resides in a separate "temporary" assembly which is called "DynamicProxyGenAssembly2". So, the InternalsVisibleTo attribute needs to be set on the target assembly to allow access to its internal members from the temporary assembly.
This happens to be common misunderstanding, for detailed information on how to use internals visible with Rhino, check this documentation page.