I have the following class:
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private MainActivity mainActivity;
public MyRunnable(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public void Run()
{
mainActivity.RunOnUiThread(() =>
{
mainActivity.ShowAlert();
});
}
}
Then I start it in OnCreate method like that:
MyRunnable myRunnable = new MyRunnable(this);
Java.Lang.Thread thread = new Java.Lang.Thread(myRunnable);
thread.Start();
But the class is too tied up with MainActivity and ShowAlert method. If I want to work with another activity and another method for example:
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private (SomeActivity) someActivity;
public MyRunnable((SomeActivity) someActivity)
{
this.someActivity = someActivity;
}
public void Run()
{
someActivity.RunOnUiThread(() =>
{
mainActivity.(SomeOtherMethod)();
});
}
}
I wouldn't be able to. Is there any way to make it more generic? (I'm using Xamarin.Android)
A simple way is to create an Action-based runnable, passing the Action as a parameter to the runnable .actr (you can also pass additional params, etc...)
C# Action in Java Runnable
public class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
readonly WeakReference<Action> actionRef;
public MyRunnable(Action action)
{
actionRef = new WeakReference<Action>(action);
}
public void Run()
{
actionRef.TryGetTarget(out Action action);
action?.Invoke();
}
}
Usage:
var runnable = new MyRunnable(async () =>
{
// Do whatever you need to do, including capturing of local vars, app/activity context, etc.
await Task.Delay(1000);
Toast.MakeText(this, "In runnable", ToastLength.Long).Show();
~~~
});
runnable.Run();
It seems that it would be easy to implement an interface-based approach:
public interface IRunnableActivity
{
void Run();
}
public class MainActivity : Activity, IRunnableActivity
{
...
public void Run()
{
ShowAlert();
}
}
public class SomeOtherActivity : Activity, IRunnableActivity
{
...
public void Run()
{
SomeOtherMethod();
}
}
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private IRunnableActivity activity;
public MyRunnable(IRunnableActivity runnableActivity)
{
activity = runnableActivity;
}
public void Run()
{
runnableActivity.RunOnUiThread(() =>
{
runnableActivity.Run();
});
}
}
I'll leave you the exercise of deciding how best to get RunOnUiThread with this approach.
You need to decouple ShowAler from MainActivity, create a Utils class, and add the method:
class Utils
{
public static void ShowAlert()
{
Android.Util.Log.Error("lv", "=======");
}
}
In your MyRunnable class, use the base class Activity to achieve polymorphism
public class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
Activity mActivity;
public MyRunnable(Activity activity)
{
mActivity = activity;
}
public void Run()
{
mActivity.RunOnUiThread(() =>
{
Utils.ShowAlert();
}
);
}
}
And then you can use the under code in any Activities:
Thread thread = new Thread(new MyRunnable(this));
thread.Start();
Related
I have a number of methods that are called on different 3rd party systems. I now have another 3rd party system that will have the same set of methods actioned against it. If both 3rd party systems are connected I will then call the methods on each object in turn.
Currently I have a class that I pass round that I can call the method once and it checks and then calls it on each system that is enabled, this has an instance of each objects classes, similar to this:
public class AACSCaller
{
3rdPartySystem1 _system1;
3rdPartySystem2 _system2;
public AACSCaller(Settings appSettings)
{
_appSettings = appSettings;
if (appSettings.system1Enabled)
{
_system1 = new 3rdPartySystem1();
}
if (appSettings.system2Enabled)
{
_system2 = new 3rdPartySystem2();
}
}
public void Method1()
{
if (appSettings.system1Enabled)
{
_system1.Method1();
}
if (appSettings.system2Enabled)
{
_system2.Method1();
}
}
public void Method2()
{
if (appSettings.system1Enabled)
{
_system1.Method2();
}
if (appSettings.system2Enabled)
{
_system2.Method2();
}
}
}
Is this sensible, as it does seem there maybe a better way and I may well be connecting additional system at some point.
A possible solution here is to define an interface or base class for 3rdPartySystem1 and 3rdPartySystem2 classes, store instances in a collection and call required methods for every item in collection. If only one system is enabled, you'll have only one item in collection, if both is enabled, you'll call them one by one in loop
public interface IThirdPartySystem
{
void Method1();
void Method2();
}
public class ThirdPartySystem1 : IThirdPartySystem
{
//implementation
}
public class ThirdPartySystem2 : IThirdPartySystem
{
//implementation
}
public class AACSCaller
{
IList<IThirdPartySystem> _systems = new List<IThirdPartySystem>();
public AACSCaller(Settings appSettings)
{
_appSettings = appSettings;
if (appSettings.system1Enabled)
{
_systems.Add(new ThirdPartySystem1());
}
if (appSettings.system2Enabled)
{
_systems.Add(new ThirdPartySystem2());
}
}
public void Method1()
{
foreach (var system in _systems)
system.Method1();
}
public void Method2()
{
foreach (var system in _systems)
system.Method2();
}
}
I suggest you to use interface that have Method1 and Method2 methods and then create to classes System1 and System2 that are implements the interface. Where AACSCaller is create you initialize the correct implementation of the interface and in your methods your just Call to the correct instance method without conditions.
public class AACSCaller
{
IThirdPartySystem ThirdPartySystem;
public AACSCaller(Settings appSettings)
{
_appSettings = appSettings;
ThirdPartySystem = appSettings.system1Enabled ? new ThirdPartySystem1() : new ThirdPartySystem2();
}
public void Method1() => ThirdPartySystem.Method1();
public void Method2() => ThirdPartySystem.Method2();
}
public interface IThirdPartySystem
{
void Method1();
void Method2();
}
public class ThirdPartySystem1 : IThirdPartySystem
{
public void Method1()
{
//code here..
}
public void Method2()
{
//code here..
}
}
public class ThirdPartySystem2 : IThirdPartySystem
{
public void Method1()
{
//code here..
}
public void Method2()
{
//code here..
}
}
Probably a bad title, but I am trying to abstract away the type "EventHub" from my generic Handler class.
I would like to inject a function instead into my subscribe method to decouple the two types. Unfortunately, the only way I can see doing this is if I make my IHandler a generic, but this causes other problems.
Is there a design pattern to decouple these two types? Commented out are lines that I would like in some way.
public interface IHandler
{
//void Subscribe(Func<Action<T>, Guid> subscribe);
void Subscribe(EventHub eventHub);
void Unsubscribe(Action<Guid> action);
}
public abstract class Handler<T> : IHandler
{
private Guid _subscriptionToken;
public virtual void Subscribe(EventHub eventHub)
{
var action = new Action<T>(Handle);
_subscriptionToken = eventHub.Subscribe(action);
}
/*public virtual void Subscribe(Func<Action<T>, Guid> subscribe)
{
var action = new Action<T>(Handle);
_subscriptionToken = subscribe(action);
}*/
public virtual void Unsubscribe(Action<Guid> action)
{
action(_subscriptionToken);
}
public abstract void Handle(T eventType);
}
Thanks for the help!
internal interface IHandler
{
void Subscribe(Func<Action<object>, Guid> subscribe);
void Unsubscribe(Action<Guid> action);
}
public abstract class Handler<T> : IHandler
{
private Guid _subscriptionToken;
public virtual void Subscribe(Func<Action<object>, Guid> subscribe)
{
var action = new Action<T>(HandleNonAsync);
_subscriptionToken = subscribe(Convert(action));
}
public virtual void Unsubscribe(Action<Guid> action)
{
action(_subscriptionToken);
}
public abstract Task HandleAsync(T eventType);
private void HandleNonAsync(T eventType)
{
HandleAsync(eventType).GetAwaiter().GetResult();
}
private Action<object> Convert(Action<T> myActionT)
{
if (myActionT == null) return null;
else return new Action<object>(o => myActionT((T)o));
}
}
I have many classes with these implementations:
internal static class WindowsServiceConfiguration<T, Y> where T : WindowsServiceJobContainer<Y>, new() where Y : IJob, new()
{
internal static void Create()
{
}
}
public class WindowsServiceJobContainer<T> : IWindowsService where T : IJob, new()
{
private T Job { get; } = new T();
private IJobExecutionContext ExecutionContext { get; }
public void Start()
{
}
public void Install()
{
}
public void Pause()
{
}
public void Resume()
{
}
public void Stop()
{
}
public void UnInstall()
{
}
}
public interface IWindowsService
{
void Start();
void Stop();
void Install();
void UnInstall();
void Pause();
void Resume();
}
public class SyncMarketCommisionsJob : IJob
{
public void Execute(IJobExecutionContext context)
{
}
}
public interface IJob
{
void Execute(IJobExecutionContext context);
}
I would like to call Create() method of WindowsServiceConfiguration static class by reflection as below:
WindowsServiceConfiguration<WindowsServiceJobContainer<SyncMarketCommisionsJob>, SyncMarketCommisionsJob>.Create();
and I don't know how to do that by using Activator or something like that in order to call Create method in my C# code?
best regards.
Something like this ought to work:
// Get the type info for the open type
Type openGeneric = typeof(WindowsServiceConfiguration<,>);
// Make a type for a specific value of T
Type closedGeneric = openGeneric.MakeGenericType(typeof(WindowsServiceJobContainer<SyncMarketCommisionsJob>), typeof(SyncMarketCommisionsJob));
// Find the desired method
MethodInfo method = closedGeneric.GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod);
// Invoke the static method
method.Invoke(null, new object[0]);
Can I create a class that inherited from thread class in c#, for my Windows Phone application.
For example :
if my class name is 'MyClass' I want to start the thread as new MyClass().Start();
Like in following Java example
public class TagIndexer
{
private static class Task
{
private String docId;
private String tags;
private String extension;
public Task(String docId, String tags, String extension)
{
this.docId = docId;
this.tags = tags;
this.extension = extension;
}
}
private static final LinkedList<Task> queue = new LinkedList<Task>();
private static boolean isWorking = false;
private static class TaskRunner extends Thread
{
#Override
public void run()
{
while (true)
{
Task task;
synchronized (queue)
{
task = queue.poll();
if (null == task)
{
isWorking = false;
break;
}
isWorking = true;
}
/*
* PROCESSING CODE
*/
}
}
}
public static void addDocument(int docId, String tags, String extension)
{
Task task = new Task(Integer.toString(docId), tags, extension);
synchronized (queue)
{
queue.add(task);
if (!isWorking)
{
new TaskRunner().start();
}
}
}
}
new MyClazz().Start();
-
public abstract class MyThread
{
public abstract void Run();
public void Start()
{
new Thread(Run).Start();
}
}
public class MyClazz : MyThread
{
public override void Run()
{
Console.WriteLine("Hello World");
}
}
On Windows Phone, Thread is a sealed class, therefore you cannot inherit from it. If you want to keep the task-based approach, you can just create a class that will wrap a thread instance. Something like:
public abstract class Task
{
protected Thread InternalThread { get; set; }
protected abstract void Run();
public void Start()
{
this.InternalThread = new Thread(this.Run);
this.InternalThread.Start();
}
}
Of course, it's just an example. You would have to add some synchronization mechanism to prevent the Start method from creating multiple threads if called more than once.
Then you can inherit it to create custom tasks:
public class MyTask : Task
{
protected override void Run()
{
// Do something
}
}
See this article about BackgroundAgent from MSDN:
Background Agents Overview for Windows Phone
I'm trying out an example of using Domain Events to notify of when something has happened in a system (borrowed from here and here).
I'm really close to getting the code working how I want, however, I've hit a bit of a brick wall. Here is my DomainEvents class:
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T : IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback); // <---- Problem here, since I can't add callback to the collection.
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (var action in Actions)
{
if (action is IEventHandler<T>)
{
((IEventHandler<T>)action).Handle(args);
}
}
}
The above won't compile because Actions.Add cannot accept callback since it's a IEventHandler<T> type rather then a IEventHandler<IDomainEvent> type. Here's some more code to clarify.
This is called from my console application:
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
CustomerHasUnpaidDuesEventHandler implements IEventHandler<CustomerHasUnpaidDuesEvent>, where CustomerHasUnpaidDuesEvent implements IDomainEvent.
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
This is what I don't get - if CustomerHasUnpaidDuesEvent implements IDomainEvent, then why is the call to Actions.Add failing? How can I resolve this?
EDIT:
To make things clearer, here is entire code for my test app:
class Program
{
static void Main()
{
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
var c = new Customer();
c.EmailAddress = "test#dfsdf.com";
c.CheckUnpaidDues();
}
}
public interface IEventHandler<in T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEmailSender
{
void SendEmail(string emailAddress);
}
public interface IDomainEvent
{
}
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T: IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (IEventHandler<T> action in Actions)
{
(action).Handle(args);
}
}
}
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public bool HasUnpaidDues { get; set; }
public void CheckUnpaidDues()
{
HasUnpaidDues = true;
DomainEvents.Raise(new CustomerHasUnpaidDuesEvent(this));
}
}
Cheers.
Jas.
There is no need for your Register method to be generic:
public static void Register(IEventHandler<IDomainEvent> callback)
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
Edit:
The problem is that in order to have IEventHandler<CustomerHasUnpaidDuesEvent> to be in the list of IEventHandler<IDomainEvent>s, we need T to be a covariant template parameter in IEventHandler<T> (which is declared as IEventHandler<out T>). However in order to allow the function Handle(T arg), we need T to be contravariant. So strictly this way won't work. Imagine: if we really could insert an IEventHandler<CustomerHasUnpaidDuesEvent> into a list of IEventHandler<IDomainEvent>s, than someone might try to call Handle with the argument of some type which derives from IDomainEvent but is not a CustomerHasUnpaidDuesEvent! This should be impossible to do.
The solution is that we don't need the exact type at Register, so we can keep a reference to a generic base interface. The implementation is here: http://ideone.com/9glmQ
Old answer is not valid, kept below for consistency.
Maybe you need to declare IEventHandler to accept T as a covariant type?
interface IEventHandler<in T> where T: IDomainEvent
{
void Handle();
// ...
}
Edit: surely CustomerHasUnpaidDuesEvent is an IDomainEvent, but you need IEventHandler<CustomerHasUnpaidDuesEvent> to be a IEventHandler<IDomainEvent>. This is exactly what covariance does. In order to allow that, your template parameter in IEventhandler must be declared covariant (<in T> instead of just <T>).