I am trying to use container.LoadConfiguration and I dont see it in the intellisense. Do I need to install or download something?
Config
<unity>
<containers>
<container>
<types>
<type type="IMyInterface, someAssembly"
mapTo="MyObject, someAssembly" />
</types>
</container>
</containers>
code
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Microsoft.Practices.Unity.InterceptionExtension.Configuration;
...
IUnityContainer _container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)System.
Configuration.ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(_container);
IEnumerable<IMyInterface> serviceList = _container.ResolveAll<IMyInterface>();
foreach (IMyInterface item in serviceList)
{
Console.Write("tet");
}
It does not go into the loop. It seems to configure ok. no errors.
If I understand your problem correctly, LoadConfiguration is not showing up in Intellisense.
I would try two things:
First makes sure you have included the Microsoft.Practices.Unity.Configuration assembly
Add an using statement for Microsoft.Practices.Unity.Configuration
LoadConfiguration is an extension method defined there.
Related
There are a lot of examples of configuring sinks and their properties using app settings configuration. However, I can't really wrap my head around configuring a custom enricher via app settings. Can this be done? I've tried to specify the configuration using the full path to my class and assembly's name, but it doesn't seem to work. Here's an example of the configuration I've tried to use:
<add key="serilog:enrich:with" value="MyApp.Logging.Serilog.MyEnricher, MyApp" />
The key-value pair syntax currently needs an extension method defined for this case to work, e.g.:
static class MyLoggerEnrichmentConfigurationExtensions
{
public static LoggerConfiguration WithMyEnricher(this LoggerEnrichmentConfiguration enrich)
{
return enrich.With(new MyEnricher());
}
}
It's then referenced and called like so:
<add key="serilog:using:MyApp" value="MyApp" />
<add key="serilog:enrich:WithMyEnricher" />
So to continue on with my first foray into Xamarin, I'm trying to develop an Content page that will take a photo, and then save the photo on the device gallery for viewing. I'm using Prism with Autofac and I'm following the wiki documentation on DependencyService and the examples that was provided on GitHub, but the program is crashing without explaining why.
I hate that!
So, here's my interface:
public interface ISavePicture
{
void SavePictureToGallery(string path);
}
ViewModel:
public class PluginPageViewModel : BindableBase
{
private ISavePicture _savePicture;
public PluginPageViewModel(ISavePicture savePicture)
{
try
{
TakePicCommand = new DelegateCommand(TakePicture);
_savePicture = savePicture;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
public ICommand TakePicCommand { get; private set; }
private async void TakePicture()
{
try
// Code here for getting the camera to take a picture ...
_savePicture.SavePictureToGallery(filePath);
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}
}
}
and the Android code:
using Android.App;
using Android.Content;
using Java.IO;
using RolodexDEMO_XF.Droid.Service;
using RolodexDEMO_XF.Services;
using Xamarin.Forms;
using Uri = Android.Net.Uri;
[assembly: Dependency(typeof(SavePicture_Android))]
namespace RolodexDEMO_XF.Droid.Service
{
public class SavePicture_Android : Activity, ISavePicture
{
public void SavePictureToGallery(string path)
{
Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
var file = new File(path);
Uri contentUri = Uri.FromFile(file);
mediaScanIntent.SetData(contentUri);
SendBroadcast(mediaScanIntent);
}
}
}
Notice that I DO have the assembly attribute for the DependencyService. I also wanted to note that I'm not using the emulator to test it out. Instead, I'm using my Galaxy Note 4 since I'm trying to test out the camera. For that part, I'm using Xamarin.Plugins from James Montemagno and that's working fine. I just can't save it, or see the pic if it is indeed saved to the device.
So where am I going wrong with it?
UPDATE: I was asked by others on what permissions I'm putting into my Android app, so in the AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="RolodexDEMOXF.RolodexDEMOXF">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:theme="#style/MyTheme" android:label="Rolodex DEMO">
<provider android:name="android.support.v4.content.FileProvider" android:authorities="RolodexDEMOXF.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="#xml/file_paths"></meta-data>
</provider>
</application>
</manifest>
and in the file_paths.xml (in the Resources\xml directory)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/RolodexDEMOXF/files/Pictures" />
<external-path name="my_movies" path="Android/data/RolodexDEMOXF/files/Movies" />
</paths>
Various members of the Prism community are committed to making the Autofac implementation of Prism for Xamarin.Forms (Prism.Autofac.Forms) excellent; so using this IoC container option is not a bad choice. The issue has been that the first version of the Autofac implementation (for Prism.Forms) was written without the knowledge that the ContainerBuilder.Update() method was being deprecated; and that Autofac containers should be immutable (i.e. built once and not updated).
Also, the Autofac implementation does not have the built-in ability to resolve dependencies via the Xamarin.Forms DependencyService, if they cannot be resolved from the Autofac IoC container. This is a known issue and is not likely to be fixed, since - as Steve points out - the integration between Prism for Xamarin.Forms and the DependencyService is being re-considered (and possibly deprecated).
So, with Autofac, you just need to perform a secondary registration of your Xamarin.Forms dependency. You can do it as Steve showed - registering platform-specific implementations in the RegisterTypes() method of your IPlatformInitializer implementation; or you can use the Xamarin.Forms DependencyService to register it in the shared (PCL) project in the App.RegisterTypes() method (in your App.xaml.cs file).
Using the Xamarin.Forms DependencyService to register it in your shared project would look like this (again, in class that inherits from PrismApplication, which is generally the App.xaml.cs file):
protected override void RegisterTypes()
{
var builder = new ContainerBuilder();
builder.Register(ctx => Xamarin.Forms.DependencyService.Get<ISavePicture>())
.As<ISavePicture>();
builder.Update(Container);
}
Final note: The information provided above is correct for version 6.3.0 of Prism.Autofac.Forms. Since things are being re-worked (possibly for Prism 7.x) to remove the ability to update Autofac containers after they are built (i.e. make them immutable); it seems likely that at some point in the future, the code above would change to:
protected override void RegisterTypes()
{
Container.Register(ctx => Xamarin.Forms.DependencyService.Get<ISavePicture>())
.As<ISavePicture>();
}
I'm putting in the answer here just in case someone else has the same problem as I do in the future. Also, since there's little documentation, and I had to cobble together this alternative solution from a Chinese website (of all places!) and discussion with some of the guys on Slate Prism-Forms channel, I thought it would be best to put it out there on the alternative solution so at least you get an rudimentary idea on to resolve the DependencyService issues, and workarounds using Autofac DI.
I do want to note that there is discussion going on the Prism GitHub that Prism's implementation of DependencyService should be depreciated and go through this alternative that I'm describing here in this post. So hopefully one of the guys on the development team will document it and give better code examples on what I'm showing here.
That said, on with the show...
Okay, so I found out the answer to the problem. Long story short, the problem is the Autofac container.
And now the long winded version.
From what I gathered Dan Siegel, of all the containers that Prism can implement for a IoC/DI container, I had to pick the one that doesn't play well with others!
Why, do I say that it doesn't play well? According to the Autofac documentation, the container is Immutable which means it cannot be modified once it's been built. So my hypothesis is that when Prism goes through the project and tries to add in the registration types of DependencyService, Autofac is balking because the container is already built and therefore the "Unhandled Exception" is being thrown.
That explains the issue, but not the solution.
And what is the solution? Well, it turns out that Brian (Lagunas) and Brian (Noyes) have implemented a new interface called IPlatformInitializer, and I therefore have no choice but to use ContainerBuilder.Update(container) to add in the new RegisterType, which implements the additional RegisterTypes for the DependencyService, and I had to implement it like this:
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainer container)
{
var temp = new ContainerBuilder();
temp.RegisterType<SavePicture_Android>().As<ISavePicture>();
temp.RegisterType<MessageService_Android>().As<IMessageService>();
// ... add more RegisterTypes as needed ...
temp.Update(container);
}
}
This class is already included in the Prism template project. For Android, it's in MainActivity.cs file.
Just in case you're wondering, it's the same for iOS and UWP. So instead of being AndroidInitializer:
iOSInitializer : IPlatformInitializer (iOS) (inside AppDelegate.cs)
UWPInitializer : IPlatformInitializer (UWP) (inside MainPage.xaml.cs)
On last thing: You can dump the [Assembly Dependency(typeof(X))] attribute since it is no longer needed. But you still need to do constructor dependency injection as they stated in their documentation for DependencyService.
As I said, the Prism gang is kicking around the idea of getting rid of their implementation of DependencyService on the next build of Prism and go down this route that I've explained to you.
It's also interesting to note is that the guys over Autofac are ALSO discussing on getting rid of the ContainerBuilder.Update() on the next version release of Autofac 4.
Just some fair warning, because of what I've put here may go out the window in the future.
I hope it helps someone out!
I am trying to monitor methods inside a .NET app which is a background process using New Relic for which I know I need to add Custom Instrumentation.
I have re-installed the .NET Agent, and after configuring "Instrument all .NET Applications", and making changes within the app.config and newrelic.config files, I am getting basic data of the background process in the new relic dashboard.
Now, to add Custom Instrumentation, I have added another instrumentation config file inside the extensions directory. Restarted the app, but still can't see the new/custom methods I am trying to monitor.
This is my instrumentation file MyInstrumentation.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- instrument EngineService.BestAgentSolver.Solve inside EngineService.BestAgentSolver -->
<tracerFactory metricName="Cast-a-Net.EngineService.BestAgentSolver.Solve-Metric">
<match assemblyName="Cast-a-Net.EngineService" className="Cast-a-Net.EngineService.BestAgentSolver">
<exactMethodMatcher methodName="Solve" />
</match>
</tracerFactory>
<!-- instrument EngineService.SessonManager.BroadcastLeadCounts inside EngineService.SessionManager -->
<tracerFactory metricName="Cast-a-Net.EngineService.SessionManager.BroadcastLeadCounts-Metric">
<match assemblyName="Cast-a-Net.EngineService" className="Cast-a-Net.EngineService.SessionManager">
<exactMethodMatcher methodName="BroadcastLeadCounts" />
</match>
</tracerFactory>
<tracerFactory metricName="myapp.Web.Controllers.CallListController.ActionResult-Metric">
<match assemblyName="myapp.Web" className="myapp.Web.Controllers.CallListController">
<exactMethodMatcher methodName="ActionResult" />
</match>
</tracerFactory>
Am I missing a step or doing something wrong?
Custom instrumentation in the .NET agent works with web transactions that use the HttpContext object. Our .NET agent API, on the other hand, allows you to collect metrics that can be displayed in a custom dashboard. In particular, RecordMetric, RecordResponseTimeMetric, and IncrementCounter are useful because they work with non-web applications.
Starting with version 2.24.218.0 of the .NET agent however, a new feature can be used to create transactions where the agent would normally not do so. This is a manual process via a custom instrumentation file.
Create a custom instrumentation file named, say CustomInstrumentation.xml, in C:\ProgramData\New Relic.NET Agent\Extensions along side CoreInstrumentation.xml. Add the following content to your custom instrumentation file:
<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
<instrumentation>
<tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Category/Name">
<match assemblyName="AssemblyName" className="NameSpace.ClassName">
<exactMethodMatcher methodName="MethodName" />
</match>
</tracerFactory>
</instrumentation>
</extension>
You must change the attribute values Category/Name, AssemblyName, NameSpace.ClassName, and MethodName above:
The transaction starts when an object of type NameSpace.ClassName from assembly AssemblyName invokes the method MethodName. The transaction ends when the method returns or throws an exception. The transaction will be named Name and will be grouped into the transaction type specified by Category. In the New Relic UI you can select the transaction type from the Type drop down menu when viewing the Monitoring > Transactions page.
Note that both Category and Name must be present and must be separated by a slash.
As you would expect, instrumented activity (methods, database, externals) occurring during the method's invocation will be shown in the transaction's breakdown table and in transaction traces.
Here is a more concrete example. First, the instrumentation file:
<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
<instrumentation>
<tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Background/Bars">
<match assemblyName="Foo" className="Foo.Bar">
<exactMethodMatcher methodName="Bar1" />
<exactMethodMatcher methodName="Bar2" />
</match>
</tracerFactory>
<tracerFactory metricName="Custom/some custom metric name">
<match assemblyName="Foo" className="Foo.Bar">
<exactMethodMatcher methodName="Bar3" />
</match>
</tracerFactory>
</instrumentation>
</extension>
Now some code:
var foo = new Foo();
foo.Bar1(); // Creates a transaction named Bars in category Background
foo.Bar2(); // Same here.
foo.Bar3(); // Won't create a new transaction. See notes below.
public class Foo
{
// this will result in a transaction with an External Service request segment in the transaction trace
public void Bar1()
{
new WebClient().DownloadString("http://www.google.com/);
}
// this will result in a transaction that has one segment with a category of "Custom" and a name of "some custom metric name"
public void Bar2()
{
// the segment for Bar3 will contain your SQL query inside of it and possibly an execution plan
Bar3();
}
// if Bar3 is called directly, it won't get a transaction made for it.
// However, if it is called inside of Bar1 or Bar2 then it will show up as a segment containing the SQL query
private void Bar3()
{
using (var connection = new SqlConnection(ConnectionStrings["MsSqlConnection"].ConnectionString))
{
connection.Open();
using (var command = new SqlCommand("SELECT * FROM table", connection))
using (var reader = command.ExecuteReader())
{
reader.Read();
}
}
}
}
Here is a simple console app that demonstrates Custom Transactions:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Custom Transactions");
var t = new CustomTransaction();
for (int i = 0; i < 100; ++i )
t.StartTransaction();
}
}
class CustomTransaction
{
public void StartTransaction()
{
Console.WriteLine("StartTransaction");
Dummy();
}
void Dummy()
{
System.Threading.Thread.Sleep(5000);
}
}
}
Use the following custom instrumentation file:
<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
<instrumentation>
<tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Background/CustomTransaction">
<match assemblyName="ConsoleApplication1" className="ConsoleApplication1.CustomTransaction">
<exactMethodMatcher methodName="StartTransaction" />
</match>
</tracerFactory>
<tracerFactory metricName="Custom/Dummy">
<match assemblyName="ConsoleApplication1" className="ConsoleApplication1.CustomTransaction">
<exactMethodMatcher methodName="Dummy" />
</match>
</tracerFactory>
</instrumentation>
</extension>
After running the application a few times you should see a custom transaction in the Other Transactions, Background category. You should see the Dummy segment in the transactions breakdown table and transaction trace.
I have two implementations of IEmailService, one for testing and one for live (is-A). And I have a BusinessService that has-A IEmailService reference.
BusinessService
IEmailService (has-A)
IEmailService
TestEmailService (is-A)
LiveEmailService (is-A)
In unity config, I register the two IEmailService implementations as follows.
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.LiveEmailService, DataAccess"
name="Live">
<lifetime type="singleton" />
</register>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.TestEmailService, DataAccess"
name="Test">
<lifetime type="singleton" />
</register>
<container>
</unity>
Based on the appSetting for IEmailService I want Unity to pick the correct implementation. This will help while testing.
<appSettings>
<add key="IEmailService" value="Test"/>
</appSettings>
The issue is when unity resolves BusinessService, it tries to resolve (none) named mapping of IEmailService instead of Live or Test and throws an ResolutionFailedException.
container.Resolve<BusinessService>(); throws below exception:
BusinessServices.Test.BusinessServiceTest_Integration.Test103:
Microsoft.Practices.Unity.ResolutionFailedException : Resolution of the dependency failed, type = "BusinessServices.BusinessService", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, DataAccess.IEmailService, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:
Resolving BusinessServices.BusinessService,(none)
Resolving parameter "emailService" of constructor BusinessServices.BusinessService(DataAccess.IEmailService emailService)
Resolving DataAccess.IEmailService,(none)
----> System.InvalidOperationException : The current type, DataAccess.IEmailService, is an interface and cannot be constructed. Are you missing a type mapping?
The workaround I came up with is to specify the registrations in code as well and have a wrapper method around container.RegisterType to register IEmailService with (none) named mapping as well based on the appSetting value.
IUnityContainer container;
// registering unity
static void Load()
{
container = new UnityContainer().LoadConfiguration();
RegisterType<IEmailService, TestEmailService>("Test");
RegisterType<IEmailService, LiveEmailService>("Live");
}
// register the `Test` or `Live` implementation with `(none)` named mapping as per appSetting
static void RegisterType<TFrom, TTo>(string name)
where TTo : TFrom
{
var tFromAppSetting= ConfigurationManager.AppSettings[typeof(TFrom).Name];
if (!string.IsNullOrEmpty(tFromAppSetting) && tFromAppSetting == name)
container.RegisterType<TFrom, TTo>();
}
This works, but I end up specifying the registrations in two places - config as well as code. Is there a better way for doing this?
Update
I actually had got it correct by code. I do not need the unity config at all. The RegisterType<TFrom, TTo>(string name) registers either the Test or Live implementation as (none) named mapping depending on appSetting value. BusinessService is also resolved without exception.
As there is no unity config, I do not have load the configuration.
container = new UnityContainer();
In my opinion the only point of having registrations in config is to not have them in code and being able to replace implementation without recompilation. So you are write in trying to remove it form code. What I don't understand is why you want to have both registrations in config in the first place. Simply remove the Live one from config for tests and the Test from config for application and register them both without name.
So for instance in application app.config:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="DataAccess.IEmailService, DataAccess"
mapTo="DataAccess.LiveEmailService, DataAccess">
<lifetime type="singleton" />
</register>
Since you really are determent to do it your way:
The other way around this is to register in code only a way of determining which instance is the default one:
container.RegisterType<IEmailService>(new InjectionFactory((c)=>
{
var name = GetImplementationsNameFromAppSettings();
return c.Resolve<IEmailService>(name);
});
I'm using my app.config to tell Unity my interface to type mappings...
<unity>
<containers>
<container>
<types>
<type type="UnityDAL.Interfaces.IDataContextFactory, UnityDAL"
mapTo="UnityDAL.UnityDemoDataContextFactory, UnityDAL" />
<type type="UnityDAL.Interfaces.IProductRepository, UnityDAL"
mapTo="UnityDAL.ProductRepository, UnityDAL" />
<type name="productRepo"
type="UnityDAL.Interfaces.IProductRepository, UnityDAL"
mapTo="UnityDAL.ProductRepository, UnityDAL" />
and so on...
using this code
var wrapper = UnityWrapper.Create();
var productRepository =
wrapper.Container.Resolve<IProductRepository>("productRepo");
var productsBO = new ProductBO(productRepository);
var products = productsBO.GetAllProducts();
Here is the constructor for the wrapper object...
public UnityWrapper()
{
_container = new UnityContainer();
var section =
(UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(_container);
}
but I get an exception that says...
{"Resolution of the dependency failed, type = \"IProductRepository\",
name = \"productRepo\". Exception message is: The current build operation
(build key Build Key[UnityDAL.ProductRepository, productRepo]) failed:
The parameter dataContextFactory could not be resolved when attempting
to call constructor UnityDAL.ProductRepository(UnityDAL.Interfaces.
IDataContextFactory dataContextFactory). (Strategy type
Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy, index 2)"}
I thought this node was wiring that up
<type type="UnityDAL.Interfaces.IDataContextFactory, UnityDAL"
mapTo="UnityDAL.UnityDemoDataContextFactory, UnityDAL" />
The idea here was originally to create a nice dependency chain. Any idea what I'm doing wrong? If you have any advice or tips on how I can correct the problem, I would like to hear them. Thanks for any help.
Cheers,
~ck in San Diego
This is a mapping problem.
Trying to resolve the UnityDAL.Interfaces.IProductRepository you need to first resolve UnityDAL.Interfaces.IDataContextFactory. Next trying to resolve UnityDAL.UnityDemoDataContextFactory you miss some mapping. Probably the ctor of the UnityDAL.UnityDemoDataContextFactory requires something that has being not registered.
By the way: what you do here is using
a service location. I avoid this
practice if possible but if you
absolutely need this then try to
expose the common service
locator. This dll ships with Unity
and provides a simple service locator
ONLY interface.