I'm trying to create an windows service application which i would be able to add modules in it as we do in WPF and Silverlight.
This is how i went throw :
public static class Program
{
public static string CurrentAppPath { get; set; }
static void Main()
{
Program.CurrentAppPath = Path.GetDirectoryName(
System.Reflection.Assembly.GetEntryAssembly().Location);
ShellBootstrapper bootstrapper = new ShellBootstrapper();
bootstrapper.Run();
}
}
And for the ShellBootstrapper class :
class ShellBootstrapper : UnityBootstrapper
{
protected override IModuleCatalog CreateModuleCatalog()
{
DirectoryModuleCatalog directoryCatalog =
new DirectoryModuleCatalog() { ModulePath = Program.CurrentAppPath };
return directoryCatalog;
}
protected override System.Windows.DependencyObject CreateShell()
{
return null;
}
public override void Run(bool runWithDefaultConfiguration)
{
base.Run(runWithDefaultConfiguration);
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService(logger)
};
ServiceBase.Run(ServicesToRun);
}
}
Are there any sample out there?
lock at this. you can download there sample as you can see in picture
After download and installing prism(v4), in root directory you have folder named as stock trader. that's what you need! (run desktop version). In section Modules you can Find folder named service.
This is simple, you can call Wcf-service in these method right here.(also you can use wcf method as async-service )
Related
Following the tutorial here I'm self hosting a WCF service inside of a windows service. My WCF service contains a global object that I update at regular intervals. I want to serialize that object to JSON and return that JSON string via a service endpoint. When I access the endpoint that calls the serialize method on the service, I get what appears to be a brand new instance of the global. The service is set to [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
I'm instantiating in the same way as the tutorial:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyWindowsService: ServiceBase
{public ServiceHost serviceHost = null;
public Service()
{
ServiceName = "MyService";
}
public static void Main()
{
ServiceBase.Run(new MyWindowsService());
}
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
serviceHost = new ServiceHost(typeof(MyWCFService));
serviceHost.Open();
}
protected override void OnStop()
{
if (serviceHost != null)
{
serviceHost.Close();
serviceHost = null;
}
}
And my WCF service looks like this:
public class MyWCFService: IWCFService
{
private myObject = mySerializableObject;
public MyWCFService()
{
myObject = new MySerializableObject();
myObject.Init();
}
public Stream GetJSON()
{
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(MySerializableObject));
ser.WriteObject(stream, myObject);
string jsonString = Encoding.ASCII.GetString(stream.ToArray());
byte[] resultBytes = Encoding.UTF8.GetBytes(jsonString);
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
return new MemoryStream(resultBytes);
}
}
If I GET the GetJSON endpoint, the string returned is a brand new initialization of the object. If I break on the GetJSON method, myObject shows all newly initialized values. Placing a breakpoint in the MySerializableObject update code shows that the updates are occurring correctly and being saved to the object in memory.
Running the same code in a normal console application works fine. Why the discrepancy? Am I handling the global incorrectly?
Figured it out ... I had a couple of issues going on.
As indicated here, my InstanceContextMode declaration
wasn't decorating the right service, so it was still running in the
default per-call context - hence, a new state object on every connection.
O'Reilly showed me that I wasn't creating my singleton
instance correctly. Side note, when creating a ServiceHost using an instance, you can specify a base URI either explicitly in the constructor or in App.config. That caused me some confusion as many of the examples I ran across passed it in the constructor rather than the config.
Here's my working implementation for posterity:
[ServiceContract(Namespace = "http://my.super.original.namespace")]
public interface IWCFService
{
[OperationContract, WebGet]
Stream GetJSON();
}
//Decorator goes on WCF service, not the Windows service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyWCFService : IWCFService
{
private StateObject _myStateObject;
public MyWCFService()
{
_myStateObject = new StateObject();
_myStateObject.Init();
}
public Stream GetJSON()
{
.
.
.
return "JSON String Here";
}
}
public class MyWindowsService : ServiceBase
{
public ServiceHost serviceHost = null;
private readonly MyWcfService _wcfSingleton;
public MyWindowsService()
{
ServiceName = "WindowsServiceNameHere";
_wcfSingleton = new MyWCFService();
}
public static void Main()
{
ServiceBase.Run(new MyWindowsService());
}
// Start the Windows service.
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
//load WCF Singleton Instance and open it for connections
serviceHost = new ServiceHost(_wcfSingleton);
serviceHost.Open();
}
protected override void OnStop()
{
if (serviceHost != null)
{
serviceHost.Close();
serviceHost = null;
}
}
}
Currently, I have 2 solutions in Visual Studio 2017:
A Windows forms application
A Windows service application hosting a WCF service class library (.dll)
And I need to communicate between them, in a cyclic way, as followed by the image below. The numbers represent the order.
The problem is, I'm actually able to communicate between WF and WCF application by using the request-replay operation contract (represented by numbers 1 and 4). But I'm not sure how to acomplhish steps 2 and 3.
Code for WCF interface:
namespace SmithWcfService {
[ServiceContract]
public interface ISmithWcfService {
[OperationContract]
void SendRequest( ); //Operation called by Windows Forms
}
}
Code for WCF interface implementation
namespace SmithWcfService {
public class SmithWcfService : ISmithWcfService {
public void SendRequest( ) {
//Ok, now I need to call Windows service application
}
}
}
Code for Windows service
namespace SmithWindowsService {
static class Program {
static void Main( ) {
ServiceBase[ ] ServicesToRun;
ServicesToRun = new ServiceBase[ ] {
new SmithWindowsService( )
};
ServiceBase.Run( ServicesToRun );
}
}
}
namespace SmithWindowsService {
public partial class SmithWindowsService : ServiceBase {
private ServiceHost host;
public SmithWindowsService( ) {
InitializeComponent( );
}
protected override void OnStart( string[ ] args ) {
host = new ServiceHost( typeof( SmithWcfService.SmithWcfService ) );
host.Open( );
}
}
}
If the windows service hosts your WCF service, you can simply pass anything it needs (callbacks, values, settings) at service start. You could pass a method of the windows service as Func<Input2, Output3> that the WCF service should call.
Without your code it's hard to tell where you need to put it though. Normally, it goes into your custom ServiceHostFactory.
Example of service with callback:
namespace SmithWcfService
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class SmithWcfService : ISmithWcfService
{
private Func<string, int> callback;
public SmithWcfService(Func<string, int> callback)
{
this.callback = callback;
}
public void SendRequest()
{
//Ok, now I need to call Windows service application:
var output = this.callback("input");
}
}
}
Example of hosting:
namespace SmithWindowsService
{
public partial class SmithWindowsService : ServiceBase
{
private ServiceHost host;
public SmithWindowsService( )
{
InitializeComponent( );
}
protected override void OnStart(string[] args)
{
var instance = new SmithWcfService.SmithWcfService(this.SomeMethodYouWantToCallIn);
host = new ServiceHost(instance, new Uri("your.url.com"));
host.Open( );
}
private int SomeMethodYouWantToCall(string data)
{
// do things...
}
}
}
I have added code in MainActivity.cs file for generating Device Id. Now I want to pass that device token to my PCL project main page, How's that possible? I also want to know about how to generate Device Token in IOS app? and how to pass that token to Portable Class Library?
Code Sample :
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
if (Intent.Extras != null)
{
foreach (var key in Intent.Extras.KeySet())
{
var value = Intent.Extras.GetString(key);
Log.Debug("Key: {0} Value: {1}", key, value);
}
}
FirebaseApp.InitializeApp(this);
var instanceId = FirebaseInstanceId.Instance;
if (FirebaseInstanceId.Instance.Token != null)
Log.Debug("MyToken", FirebaseInstanceId.Instance.Token.ToString());
}
}
I need this "My Token" data on login page button Click event. Hows this possible?
My Login Page Code is
public partial class LoginPage : ContentPage
{
private readonly DataService _dataService = new DataService();
public LoginPage()
{
InitializeComponent();
}
private async Task BtnLogin_ClickedAsync(object sender, EventArgs e)
{
var result = await _dataService.Authentication(TxtUserName.Text, TxtPassword.Text,"MyToken");
if (result.AccessToken != null)
{
await Navigation.PushModalAsync(new MainMasterPage());
GlobalClass.userToken = result;
}
else
await DisplayAlert("", Resource.InvalidMessage, Resource.OkText);
}
}
Welcome to the Realm of Dependency Injection :)
documentation can be found here
You need to create a interface on your PCL then reference that on your Native project
Example:
Create class DeviceToke.cs in your PCL
public interface ITextToSpeech
{
void Speak(string text);
}
Then in your native project, you can do the following:
sample code:
[assembly: Dependency(typeof(TextToSpeechAndroidImpl))]
namespace IocAndDiXamarinForms.Droid
{
public class TextToSpeechAndroidImpl : Java.Lang.Object, ITextToSpeech, TextToSpeech.IOnInitListener
{
TextToSpeech speaker;
string toSpeak;
public void Speak(string text)
{
var ctx = Forms.Context; // useful for many Android SDK features
toSpeak = text;
if (speaker == null)
{
speaker = new TextToSpeech(ctx, this);
}
else
{
var p = new Dictionary<string, string>();
speaker.Speak(toSpeak, QueueMode.Flush, p);
}
}
#region IOnInitListener implementation
public void OnInit(OperationResult status)
{
if (status.Equals(OperationResult.Success))
{
var p = new Dictionary<string, string>();
speaker.Speak(toSpeak, QueueMode.Flush, p);
}
}
#endregion
}
}
You can use the Xamarin messaging center to pass a message back from your platform-specific classes to your PCL ViewModel. You'll need to subscribe to the message in your VM, and send the message from your Android or iOS class. Then you can store the value in your VM and use it when the user clicks login.
Sending the message:
Xamarin.Forms.MessagingCenter.Send(FirebaseInstanceId.Instance.Token.ToString(), "InstanceId");
Subscribing in your VM:
MessagingCenter.Subscribe<string> (this, "InstanceId", (InstanceId) => {
// use the InstanceId as required
});
});
A handy solution is to define a publicly accessible static StrToken property in some public class, e.g. App:
public static Size Token;
and OnCreate on Android:
App.StrToken = FirebaseInstanceId.Instance;
I am trying to implement inversion of control (IoC) in order to develop a plug-in based application, which needs to be able to pass data (e.g. strings) back to my main EXE when something happens. To achieve this, I am passing an Action to the DLL which it can use to send data back to the EXE. The following code shows a little test application to explain my beginner-problem:
namespace MainExe
{
class Program
{
[Import(typeof(IDataProvider))]
public IDataProvider stringProvider { get; set; }
public void myCallback(string str)
{
Console.WriteLine(str);
}
public Program()
{
try
{
AggregateCatalog aggregatecatalogue = new AggregateCatalog();
aggregatecatalogue.Catalogs.Add(new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory));
CompositionContainer container = new CompositionContainer(aggregatecatalogue);
container.ComposeParts(this);
}
catch (FileNotFoundException fnfex)
{
Console.WriteLine(fnfex.Message);
}
catch (CompositionException cex)
{
Console.WriteLine(cex.Message);
}
}
void Run()
{
if (stringProvider != null)
{
stringProvider.SaySomething("myrequest", myCallback);
Console.ReadKey();
}
}
static void Main(string[] args)
{
Program program = new Program();
program.Run();
}
}
}
My Interface looks like this:
namespace DataInterfaceDll
{
public interface IDataProvider
{
void SaySomething(string request, Action<string> callback);
}
}
And this is the Plug-In (DLL), which should be able to send something back to the EXE (or call a function from the EXE that does this):
namespace StringDataDll
{
[Export(typeof(IDataProvider))]
public class StringData : IDataProvider
{
public void SaySomething(string request, Action<string> callback)
{
callback("This is just a test program...");
}
}
}
When I run this code, I get a System.Reflection.ReflectionTypeLoadException in the following line
container.ComposeParts(this);
Can anyone tell me what I am doing wrong here?
It works for me by loading dynamically the DLL.
aggregatecatalogue.Catalogs.Add(new AssemblyCatalog(Assembly.LoadFile("yourpath\StringDataDll.dll")));
aggregatecatalogue.Catalogs.Add(new AssemblyCatalog(Assembly.GetAssembly(typeof(IDataProvider))));
And it works too with new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory) when you copy the stringDataDll.dll in the output folder of your main program.
Be sure to have all of your dll files in your output folder of your main program.
I've previously used log4net, but my current employer uses Enterprise Library application blocks. I had previously developed unit tests for my core logging classes as follows and was wondering if someone knew the equivalent for the OneTimeSetup code below for the logging app block (sorry for the long code post):
public abstract class DataGathererBase
{
public readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void CollectData()
{
this.LogDebug("Initialize started");
}
public static class Logger
{
private static LoggingSettings settings = LoggingSettings.GetLoggingSettings(new SystemConfigurationSource());
static Logger()
{
log4net.Config.XmlConfigurator.Configure();
}
public static void LogDebug(this DataGathererBase current, string message)
{
if (current.logger.IsDebugEnabled)
{
current.logger.Debug(string.Format("{0} logged: {1}", current.GetType().Name, message));
}
}
}
[TestFixture]
public class LoggerTests:DataGathererBase
{
private ListAppender appender;
private static ILog log;
[TestFixtureSetUp]
public void OneTimeSetup()
{
appender = new ListAppender();
appender.Layout = new log4net.Layout.SimpleLayout();
appender.Threshold = log4net.Core.Level.Fatal;
log4net.Config.BasicConfigurator.Configure(appender);
log = LogManager.GetLogger(typeof(ListAppender));
}
[Test]
public void TestLogging()
{
this.LogDebug("Debug");
Assert.AreEqual(0, ListAppender.logTable.Count());
}
}
Enterprise Library 5.0 introduced a fluent interface which can be used to programmatically configure the application blocks. You will probably find this to be a more comfortable option.
To give credit, this answer is based on a David Hayden article which is based on an Alois Kraus article, Programatic Configuraton - Enterprise Library (v2.0) Logging Block . Read those two articles for a good look at programmatic access to Enterprise Library logging.
I wasn't familiar with ListAppender so I created a CustomTraceListener that sticks the log messages in a List<string>:
public class ListAppender : Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.CustomTraceListener
{
private List<string> list = new List<string>();
public override void Write(string message)
{
}
public override void WriteLine(string message)
{
list.Add(message);
}
public List<string> LogTable
{
get
{
return list;
}
}
}
Here is a modified LoggerTests class that programmatically accesses the EL logging classes to setup the tests (this does not use NUnit):
public class LoggerTests
{
private ListAppender appender;
private static LogWriter log;
public void OneTimeSetup()
{
appender = new ListAppender();
// Log all source levels
LogSource mainLogSource = new LogSource("MainLogSource", SourceLevels.All);
mainLogSource.Listeners.Add(appender);
// All messages with a category of "Error" should be distributed
// to all TraceListeners in mainLogSource.
IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();
traceSources.Add("Error", mainLogSource);
LogSource nonExistentLogSource = null;
log = new LogWriter(new ILogFilter[0], traceSources, nonExistentLogSource,
nonExistentLogSource, mainLogSource, "Error", false, false);
}
public void TestLogging()
{
LogEntry le = new LogEntry() { Message = "Test", Severity = TraceEventType.Information };
le.Categories.Add("Debug");
log.Write(le);
// we are not setup to log debug messages
System.Diagnostics.Debug.Assert(appender.LogTable.Count == 0);
le.Categories.Add("Error");
log.Write(le);
// we should have logged an error
System.Diagnostics.Debug.Assert(appender.LogTable.Count == 1);
}
}