How to get GPS or Location - xamarin.android

I tried the tutorial GPS and I got the following error messages. What seems to be the problems?
http://docs.xamarin.com/recipes/android/os_device_resources/gps/get_current_device_location
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
//-- added these
using Android.Locations;
using System.Collections.Generic;
using System.Threading;
using System.Text;
namespace GetLocation
{
[Activity(Label = "Get Location", MainLauncher = true, Icon = "#drawable/icon")]
public class Activity1 : Activity, ILocationListener
{
//int count = 1;
private Location _currentLocation;
private LocationManager _locationManager;
private TextView _locationText;
private TextView _addressText;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView(Resource.Layout.Main);
_addressText = FindViewById(Resource.Id.address_text);
_locationText = FindViewById(Resource.Id.location_text);
FindViewById(Resource.Id.get_address_button).Click += AddressButton_OnClick;
InitializeLocationManager();
}
//public void OnLocationChanged(Location location) {}
public void OnProviderDisabled(string provider) {}
public void OnProviderEnabled(string provider) {}
public void OnStatusChanged(string provider, Availability status, Bundle extras) {}
private void InitializeLocationManager()
{
_locationManager = (LocationManager) GetSystemService(LocationService);
var criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
var acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = String.Empty;
}
}
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
private void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
if (_currentLocation == null)
{
_addressText.Text = "Can't determine the current location.";
return;
}
new Thread(() =>
{
var addressText = "Unable to find a location.";
var geocoder = new Geocoder(this);
var addressList = geocoder.GetFromLocation(_currentLocation.Latitude, _currentLocation.Longitude, 50);
var address = addressList.FirstOrDefault();
if (address != null)
{
var deviceLocation = new StringBuilder();
for (var i = 0; i { _addressText.Text = addressText; });
}).Start();
}
public void OnLocationChanged(Location location)
{
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location.";
}
else
{
_locationText.Text = String.Format("{0},{1}", _currentLocation.Latitude, _currentLocation.Longitude);
}
}
}
}
How to solve these problems:
Error messages
1)
Error CS1061: 'System.Collections.Generic.IList' does not
contain a definition for 'Any' and no extension method 'Any' accepting
a first argument of type 'System.Collections.Generic.IList'
could be found (are you missing a using directive or an assembly
reference?) (CS1061) (GetLocation)
2)Error CS0103: The name '_locationProvider' does not exist in the current context (CS0103) (GetLocation)
3)Error CS1061: 'System.Collections.Generic.IList<string>' does not contain a definition for 'First' and no extension method 'First' accepting a first argument of type 'System.Collections.Generic.IList<string>' could be found (are you missing a using directive or an assembly reference?) (CS1061) (GetLocation)
4)Error CS0103: The name '_locationProvider' does not exist in the current context (CS0103) (GetLocation)
5) Error CS1061: 'System.Collections.Generic.IList<Android.Locations.Address>' does not contain a definition for 'FirstOrDefault' and no extension method 'FirstOrDefault' accepting a first argument of type 'System.Collections.Generic.IList<Android.Locations.Address>' could be found (are you missing a using directive or an assembly reference?) (CS1061) (GetLocation)
6) Does it matter if File name is MainActivity.cs and Activity Class is called:
public class Activity1 : Activity, ILocationListener
{
}
Thanks

to use the definition of "Any()" you must have "using System.Linq".
Hope that helps.

Related

Some services are not able to be constructed using the library : NetCore.AutoRegisterDi

I am developing asp.net core 3.1 GraphQL based APIs. I used the below reference article to setup automatic DI configuration in the API layer and have used the nuget package : NetCore.AutoRegisterDi
https://www.thereformedprogrammer.net/asp-net-core-fast-and-automatic-dependency-injection-setup/
Here goes the code details:
Code:
Startup.cs:
public virtual void ConfigureServices(IServiceCollection services) => services
.AddGraphQLResolvers()
.AddProjectRepositories();
ProjectServiceCollectionExtensions.cs
public static class ProjectServiceCollectionExtensions
{
public static IServiceCollection AddProjectRepositories(this IServiceCollection services) =>
services.RegisterAssemblyPublicNonGenericClasses(Assembly.GetAssembly(typeof(CommonService)))
.Where(c => c.Name.EndsWith("Persistence"))
.AsPublicImplementedInterfaces(ServiceLifetime.Scoped);
public static IServiceCollection AddGraphQLResolvers(this IServiceCollection services) =>
services
.AddScoped<ICountriesResolver, CountriesResolver>()
.AddScoped<ICountryGroupsResolver, CountryGroupsResolver>()
.AddScoped<IDisclaimerResolver, DisclaimerResolver>();
}
Here in the above CommonService is part of the Service Layer that ends with Persistence.
CountriesResolver.cs
public class CountriesResolver : Resolver, ICountriesResolver
{
private readonly ICountryService _countryService;
private readonly IHttpContextAccessor _accessor;
private readonly IDataLoaderContextAccessor _dataLoaderContextAccessor;
public CountriesResolver(ICountryService countryService, IHttpContextAccessor accessor, IDataLoaderContextAccessor dataLoaderContextAccessor)
{
_countryService = countryService ?? throw new ArgumentNullException(nameof(countryService));
_accessor = accessor;
_dataLoaderContextAccessor = dataLoaderContextAccessor;
}
public void Resolve(GraphQLQuery graphQLQuery)
{
var language = _accessor.HttpContext.Items["language"] as LanguageDTO;
graphQLQuery.FieldAsync<ResponseGraphType<CountryResultType>>("countriesresponse", arguments: new QueryArguments(new QueryArgument<IdGraphType>{Name = "pageNo", Description = "page number"}, new QueryArgument<IdGraphType>{Name = "pageSize", Description = "page size"}), resolve: async context =>
{
var pageNo = context.GetArgument<int>("pageNo") == 0 ? 1 : context.GetArgument<int>("pageNo");
var pageSize = context.GetArgument<int>("pageSize") == 0 ? 100 : context.GetArgument<int>("pageSize");
if (language != null)
{
var loader = _dataLoaderContextAccessor.Context.GetOrAddLoader("GetAllCountries", () => _countryService.GetAllCountriesAsync(language, pageNo, pageSize));
var list = await context.TryAsyncResolve(async c => await loader.LoadAsync());
return Response(list);
}
return null;
}
, description: "All Countries data");
}
}
ICommonService.cs
using Author.Query.Persistence.DTO;
using System.Threading.Tasks;
namespace Author.Query.Persistence.Interfaces
{
public interface ICommonService
{
LanguageDTO GetLanguageFromLocale(string locale);
Task<LanguageDTO> GetLanguageFromLocaleAsync(string locale);
}
}
CommonService.cs
namespace Author.Query.Persistence
{
public class CommonService : ICommonService
{
private readonly AppDbContext _dbContext;
private readonly IOptions<AppSettings> _appSettings;
private readonly IMapper _mapper;
private readonly ICacheService<Languages, LanguageDTO> _cacheService;
public CommonService(AppDbContext dbContext, IOptions<AppSettings> appSettings, IMapper mapper, ICacheService<Languages, LanguageDTO> cacheService)
{
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
_appSettings = appSettings;
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
_cacheService = cacheService ?? throw new ArgumentNullException(nameof(cacheService));
}
//public Languages GetLanguageFromLocale(string locale)
public LanguageDTO GetLanguageFromLocale(string locale)
{
return GetLanguagesByFilter(GetFilterValues(locale, true).ToArray());
}
}
}
ICountryService.cs
namespace Author.Query.Persistence.Interfaces
{
public interface ICountryService
{
Task<CountryResult> GetAllCountriesAsync(LanguageDTO language, int pageNo, int pageSize);
Task<CountryDTO> GetCountryAsync(LanguageDTO language, int countryId);
}
}
CountryService.cs
namespace Author.Query.Persistence
{
public class CountryService : ICountryService
{
private readonly AppDbContext _dbContext;
private readonly IOptions<AppSettings> _appSettings;
private readonly ICacheService<Images, ImageDTO> _cacheService;
public CountryService(TaxathandDbContext dbContext, IOptions<AppSettings> appSettings, ICacheService<Images, ImageDTO> cacheService)
{
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
_cacheService = cacheService ?? throw new ArgumentNullException(nameof(cacheService));
_appSettings = appSettings;
}
public async Task<CountryResult> GetAllCountriesAsync(LanguageDTO language, int pageNo, int pageSize)
{
var localeLangId = language.LanguageId;
var dftLanguageId = int.Parse(_appSettings.Value.DefaultLanguageId);
// By default pick the localLanguage value
var countries = await GetAllCountriesDataAsync(localeLangId, pageNo, pageSize);
// If localLanguage data is not available then pull the data based on default language
if (countries.Countries.Count == 0)
{
countries = await GetAllCountriesDataAsync(dftLanguageId, pageNo, pageSize);
}
return countries;
}
public async Task<CountryDTO> GetCountryAsync(LanguageDTO language, int countryId)
{
var localeLangId = language.LanguageId;
var dftLanguageId = int.Parse(_appSettings.Value.DefaultLanguageId);
//var country = new CountryDTO();
// By default pick the localLanguage value
var country = await GetCountryDetailsAsync(countryId, localeLangId);
// If localLanguage data is not available then pull the data based on default language
if (country == null)
{
country = await GetCountryDetailsAsync(countryId, dftLanguageId);
}
return country;
}
private async Task<CountryDTO> GetCountryDetailsAsync(int countryId, int languageId)
{
var images = await _cacheService.GetAllAsync("imagesCacheKey");
var country = await _dbContext.Countries.AsNoTracking().FirstOrDefaultAsync(c => c.CountryId.Equals(countryId) && c.IsPublished.Equals(true) && c.LanguageId.Equals(languageId));
if (country == null)
{
return null;
}
var countryDTO = new CountryDTO{Uuid = country.CountryId, PNGImagePath = images.FirstOrDefault(im => im.ImageId.Equals(country.PNGImageId)).FilePath, SVGImagePath = images.FirstOrDefault(im => im.ImageId.Equals(country.SVGImageId)).FilePath, DisplayName = country.DisplayName, DisplayNameShort = country.DisplayName, Name = Helper.ReplaceChars(country.DisplayName), Path = Helper.ReplaceChars(country.DisplayName), CompleteResponse = true};
return countryDTO;
}
private async Task<CountryResult> GetAllCountriesDataAsync(int languageId, int pageNo, int pageSize)
{
var countryList = new CountryResult();
var images = await _cacheService.GetAllAsync("imagesCacheKey");
var countries = await _dbContext.Countries.Where(cc => cc.IsPublished.Equals(true) && cc.LanguageId.Equals(languageId)).Select(c => new
{
c.CountryId, c.DisplayName, c.PNGImageId, c.SVGImageId
}
).OrderByDescending(c => c.CountryId).Skip((pageNo - 1) * pageSize).Take(pageSize).AsNoTracking().ToListAsync();
if (countries.Count == 0)
{
return null;
}
countryList.Countries.AddRange(countries.Select(co => new CountryDTO{Uuid = co.CountryId, PNGImagePath = images.FirstOrDefault(im => im.ImageId.Equals(co.PNGImageId)).FilePath, SVGImagePath = images.FirstOrDefault(im => im.ImageId.Equals(co.SVGImageId)).FilePath, DisplayName = co.DisplayName, DisplayNameShort = co.DisplayName, Name = Helper.ReplaceChars(co.DisplayName), Path = Helper.ReplaceChars(co.DisplayName), CompleteResponse = true}));
return countryList;
}
}
}
Error:
System.AggregateException
HResult=0x80131500
Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Author.Query.New.API.GraphQL.Resolvers.ICountriesResolver Lifetime: Scoped ImplementationType: Author.Query.New.API.GraphQL.Resolvers.CountriesResolver':
Unable to resolve service for type 'Author.Query.Persistence.Interfaces.ICountryService' while attempting to activate 'Author.Query.New.API.GraphQL.Resolvers.CountriesResolver'.) (Error while validating the service descriptor 'ServiceType:
Author.Query.New.API.GraphQL.Resolvers.ICountryGroupsResolver Lifetime: Scoped ImplementationType: Author.Query.New.API.GraphQL.Resolvers.CountryGroupsResolver': Unable to resolve service for type 'Author.Query.Persistence.Interfaces.ICountryGroupService' while attempting to activate 'Author.Query.New.API.GraphQL.Resolvers.CountryGroupsResolver'.) (Error while validating the service descriptor 'ServiceType: Author.Query.New.API.GraphQL.Resolvers.IDisclaimerResolver Lifetime: Scoped ImplementationType: Author.Query.New.API.GraphQL.Resolvers.DisclaimerResolver': Unable to resolve service for type 'Author.Query.Persistence.Interfaces.IDisclaimerService' while attempting to activate 'Author.Query.New.API.GraphQL.Resolvers.DisclaimerResolver'.)
Source=Microsoft.Extensions.DependencyInjection
StackTrace:
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at Author.Query.New.API.Program.Main(String[] args) in /src/QueryStack/Author.Query.New.API/Program.cs:line 15
Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: Author.Query.New.API.GraphQL.Resolvers.ICountriesResolver Lifetime: Scoped ImplementationType:
Author.Query.New.API.GraphQL.Resolvers.CountriesResolver':
Unable to resolve service for type 'Author.Query.Persistence.Interfaces.ICountryService' while attempting to activate
'Author.Query.New.API.GraphQL.Resolvers.CountriesResolver'.
Inner Exception 2:
InvalidOperationException: Unable to resolve service for type
'Author.Query.Persistence.Interfaces.ICountryService' while attempting to activate
'Author.Query.New.API.GraphQL.Resolvers.CountriesResolver'.
Can anyone help me to know how to fix this issue?
The error says that :
Unable to resolve service for type
'Author.Query.Persistence.Interfaces.ICountryService' while attempting to activate
'Author.Query.New.API.GraphQL.Resolvers.CountriesResolver'
ICountryService is never registered. AddGraphQLResolvers registers only ICountriesResolver, ICountryGroupsResolver and IDisclaimerResolver.
The method AddProjectRepositories only registers classes whose name ends in Persistence that appear in the same namespace as CommonService. It never registers CommonService itself.
The service must be registered, eg with :
services.AddScoped<ICommonService, CommonService>();
Your method AddProjectRepositories() does not register CountryService, because the Where filter in RegisterAssemblyPublicNonGenericClasses() looks at classes (Type), not at namespaces.
So perhaps you can change your filter:
services.RegisterAssemblyPublicNonGenericClasses(Assembly.GetAssembly(typeof(CommonService)))
.Where(c => c.Name.EndsWith("Service")) // <-- Change "Persistence" to "Service"
.AsPublicImplementedInterfaces(ServiceLifetime.Scoped);
That should register all classes that end with "Service" in the Assembly that contains CommonService.
For me it was a simple mistake. I had a class with the same name in another namespace and referenced the wrong class/forgot to delete the duplicate class and add the correct one to my startup.
I had a service called UserService in myapp.Utils and another in myapp.Services. I was referencing myapp.Utils when I meant to delete that one and only use myapp.Services. I was incorrectly injecting the one in myapp.Utils when my controllers were set up to use the one in myapp.Services.

Sitecore Microsoft Dependency Injection error "Service has been disposed, cannot create object"

I am using Sitecore 8.2 Update 4 with Helix framework also using Microsoft Extension Dependency Injection. I have performed few steps for DI:
1. Created DI project in Foundation layer.
2. I have created on pipeline with name Habitat.Foundation.DI.RegisterControllers inside
App_config/Include/zFoundation
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"><sitecore> <services> <configurator type=" Habitat.Foundation.DI.RegisterControllers, Habitat.Foundation.DI" /></services></sitecore></configuration>
namespace Habitat.Foundation.DI{ public class RegisterControllers : IServicesConfigurator
{
public void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddMvcControllers("*.Feature.*");
}
}}
namespace Habitat.Foundation.DI.Extensions{
public static class ServiceCollectionExtensions
{
public static void AddMvcControllers(this IServiceCollection serviceCollection, params string[] assemblyFilters)
{
var assemblies = GetAssemblies.GetByFilter(assemblyFilters);
AddMvcControllers(serviceCollection, assemblies);
}
public static void AddMvcControllers(this IServiceCollection serviceCollection, params Assembly[] assemblies)
{
var controllers = GetTypes.GetTypesImplementing<IController>(assemblies)
.Where(controller => controller.Name.EndsWith("Controller", StringComparison.Ordinal));
foreach (var controller in controllers)
serviceCollection.AddTransient(controller);
controllers = GetTypes.GetTypesImplementing<ApiController>(assemblies)
.Where(controller => controller.Name.EndsWith("Controller", StringComparison.Ordinal));
foreach (var controller in controllers)
serviceCollection.AddTransient(controller);
}
}}
public static class GetAssemblies
{
public static Assembly[] GetByFilter(params string[] assemblyFilters)
{
var assemblyNames = new HashSet<string>(assemblyFilters.Where(filter => !filter.Contains('*')));
var wildcardNames = assemblyFilters.Where(filter => filter.Contains('*')).ToArray();
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(assembly =>
{
var nameToMatch = assembly.GetName().Name;
if (assemblyNames.Contains(nameToMatch)) return true;
return wildcardNames.Any(wildcard => IsWildcardMatch(nameToMatch, wildcard));
})
.ToArray();
return assemblies;
}
/// <summary>
/// Checks if a string matches a wildcard argument (using regex)
/// </summary>
private static bool IsWildcardMatch(string input, string wildcards)
{
return Regex.IsMatch(input, "^" + Regex.Escape(wildcards).Replace("\\*", ".*").Replace("\\?", ".") + "$",
RegexOptions.IgnoreCase);
}
}public static class GetTypes {
public static Type[] GetTypesImplementing<T>(params Assembly[] assemblies)
{
if (assemblies == null || assemblies.Length == 0)
return new Type[0];
var targetType = typeof(T);
return assemblies
.Where(assembly => !assembly.IsDynamic)
.SelectMany(GetExportedTypes)
.Where(type => !type.IsAbstract && !type.IsGenericTypeDefinition && targetType.IsAssignableFrom(type))
.ToArray();
}
private static IEnumerable<Type> GetExportedTypes(Assembly assembly)
{
try
{
return assembly.GetExportedTypes();
}
catch (NotSupportedException)
{
// A type load exception would typically happen on an Anonymously Hosted DynamicMethods
// Assembly and it would be safe to skip this exception.
return Type.EmptyTypes;
}
catch (ReflectionTypeLoadException ex)
{
// Return the types that could be loaded. Types can contain null values.
return ex.Types.Where(type => type != null);
}
catch (Exception ex)
{
// Throw a more descriptive message containing the name of the assembly.
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
"Unable to load types from assembly {0}. {1}", assembly.FullName, ex.Message), ex);
}
}
}
As I am using Glass Mapper so I want to use ISitecoreContext, for that I have register ISitecoreContext in Foundation/ORM for that I have performed these actions:
1. Created patch file inside Foundation/ORM
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"><sitecore><services>
<configurator type="Habitat.Foundation.ORM.DI.RegisterContainer, Habitat.Foundation.ORM" />
</services> </sitecore>
public class RegisterContainer : IServicesConfigurator
{
public void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddTransient<ISitecoreContext, SitecoreContext>();
}
}
Accesssing in controller like this
private readonly ISitecoreContext _sitecoreContext;
public TestController(ISitecoreContext sitecoreContext)
{
_sitecoreContext = sitecoreContext;
}
I accessing in two classes one way is _sitecoreContext.GetItem(Context.Site.ContentStartPath) and another way is _sitecoreContext.GetRootItem() then it started throwing error “{"Service has been disposed, cannot create object"}” in _sitecoreContext.GetItem(Context.Site.ContentStartPath) but working for
_sitecoreContext.GetRootItem()
When I update AddTransient to AddSingleton then it works for some time for both but for after some time it started giving me null value of _sitecoreContext.
Please help me.

Resolve named Dependencies with Dependency Resolver

I've noticed that when I register my dependencies via named overrides Dependency Resolver struggles to resolve components properly. Seems like the first instance is provided. Everything is fine with ctor injection.
Example:
Registration
RegisterProvider<IAccountProvider, AccountProvider>();
RegisterProvider<IAccountProvider, CustomAccountProvider>("customAccountProvider");
Resolution
var instance = DependecyResolver.Current.GetService<IAccountProvider>();
Cannot retrieve customAccountProvider instance.
It always refers to the first registered component ignoring named constraints.
When you have multiple implementations of the same component you have to name them or mark them with marking interface. Here is a code example with naming the instances :
using System;
using System.Linq;
using System.Reflection;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
namespace ResolvingNamedInctances
{
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>().ImplementedBy<AccountProviderTypeSelector>());
container.Register(Component.For<IAccountProviderSelector>().AsFactory(typeof(AccountProviderTypeSelector)));
container.Register(Component.For<IAccountProvider>().ImplementedBy<DefaultAccountProvider>().Named("default"));
container.Register(Component.For<IAccountProvider>().ImplementedBy<CustomAccountProvider>().Named("custom"));
// uncomment this line in MVC app and use DependencyResolver instead of container
//DependencyResolver.SetResolver(new WindsorDependencyResolver(container.Kernel));
var accountProviderSelector = container.Resolve<IAccountProviderSelector>();
var defaultAccountProvider = accountProviderSelector.GetAccountProvider(); // default
defaultAccountProvider.Provide();
var customAccountProvider = accountProviderSelector.GetAccountProvider("custom");
customAccountProvider.Provide();
Console.ReadLine();
}
}
public class AccountProviderTypeSelector : ITypedFactoryComponentSelector
{
public Func<IKernelInternal, IReleasePolicy, object> SelectComponent(MethodInfo method, Type type, object[] arguments)
{
string providerName = arguments.Length > 0 ? (string)arguments[0] : "default";
return (k, r) => k.GetHandlers(typeof(IAccountProvider))
.Where(
h =>
{
return h.ComponentModel.Name == providerName;
})
.Select(h => (IAccountProvider)k.Resolve(
h.ComponentModel.Name,
typeof(IAccountProvider),
new Arguments { },
r))
.FirstOrDefault();
}
}
public interface IAccountProviderSelector
{
IAccountProvider GetAccountProvider();
IAccountProvider GetAccountProvider(string nameIdentifier);
}
public interface IAccountProvider
{
void Provide();
}
public class DefaultAccountProvider : IAccountProvider
{
public void Provide()
{
Console.WriteLine("Working in default AccountProvider");
}
}
public class CustomAccountProvider : IAccountProvider
{
public void Provide()
{
Console.WriteLine("Working in standart CustomAccountProvider");
}
}
}

structuremap in IOC

I want to use structuremap in ioc .
this is my code:
public class StructureMapDependencyResolverConfigurator : IDependencyResolverConfigurator
{
public static bool _isStarted = false;
public void Configure()
{
ObjectFactory.Initialize(x =>
{
try
{
RegisterTypesFromAssembly("ImenBourse.Data", "ImenBourse.Data.AdoSql", typeof(IDaoBase), x);
RegisterTypesFromAssembly("ImenBourse.Data", "ImenBourse.Data.AdoSql", typeof(IQueryBase), x);
RegisterTypesFromAssembly("ImenBourse.Domain.Service", "ImenBourse.Domain.Impl", typeof(IServiceBase), x);
}
catch (Exception e)
{
}
});
}
public IControllerFactory ControllerFactory { get { return new StructureMapControllerFactory(); } }
public IContainer Container { get { return ObjectFactory.Container; } }
private void RegisterTypesFromAssembly(string assemblyInterfaceName, string assemblyImplName, Type baseType, IInitializationExpression initializer)
{
Assembly intAssembly = Assembly.Load(assemblyInterfaceName);
var interfaceList = intAssembly.GetTypes().Where(assemblyType => assemblyType.IsInterface && baseType.IsAssignableFrom(assemblyType) && baseType != assemblyType).ToList();
if (interfaceList.Count == 0)
interfaceList = intAssembly.GetTypes().Where(assemblyType => assemblyType.IsInterface && baseType != assemblyType).ToList();
Assembly implAssembly = Assembly.Load(assemblyImplName);
var implList = implAssembly.GetTypes().Where(assemblyType => assemblyType.IsClass && baseType.IsAssignableFrom(assemblyType)).ToList();
foreach (var type in interfaceList)
{
foreach (var implType in implList)
{
if (type != implType && type.IsAssignableFrom(implType))
{
initializer.ForRequestedType(type).Use(implType);
}
}
}
}
when I call RegisterTypesFromAssembly function,this line has a error
Assembly implAssembly = Assembly.Load(assemblyImplName);
and i see this error:
Could not load file or assembly 'ImenBourse.Data.AdoSql' or one of its dependencies.The system cannot find the file specified.
and ImenBourse.Data.AdoSql assembly is :
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ImenBourse.Data.AdoSql")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ImenBourse.Data.AdoSql")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
what is error in my code that i have an error
Try adding the ".dll" to the assembly name in RegisterTypesFromAssembly. It seems to be looking for a file without the extension:
RegisterTypesFromAssembly("ImenBourse.Data", "ImenBourse.Data.AdoSql.dll", typeof(IDaoBase), x);

Autofac and injection of instances

In a ASP.NET MVC project I'm working on I have the following piece of code that basically inject instances to specific methods within my assemblies.
So in the application root I have a class that register the instances like this and finally handles the injection.
ApplicationServiceProvider serviceProvider = ApplicationServiceProvider.CreateDefaultProvider();
serviceProvider.RegisterInstance(GlobalConfiguration.Configuration);
serviceProvider.RegisterInstance(GlobalFilters.Filters);
serviceProvider.RegisterInstance(RouteTable.Routes);
serviceProvider.RegisterInstance(BundleTable.Bundles);
serviceProvider.Distribute();
Now when I want to access these instances from the assemblies, I have to create some handler (method) and mark it with the following attribute 'ApplicationServiceHandler' like in the following example.
[ContractVerification(false)]
public static class RouteConfiguration
{
[ApplicationServiceHandler]
public static void Register(RouteCollection routes)
{
}
}
This is part of the extensibility layer in the project which is currently working pretty good.
Now, I'm new to Autofac and I wonder whether I can use Autofac to do the work for me rather than using my own implementation (which I provided below) that probably does it less efficient and handles less cases that are already covered by Autofac.
I noticed Autofac have a RegisterInstance method but I'm not sure how to tell it to inject the instances to methods flagged with 'ApplicationServiceHandler' attribute, I'm not not sure it's even the correct method but based on the name it seems like the right one.
Any kind of help is greatly appreciated, thank you.
EDIT: Here is the code that I'm using to achieve this without Autofac in my project.
ApplicationServiceHandlerAttribute.cs
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ApplicationServiceHandlerAttribute : Attribute
{
}
ApplicationServiceHandler.cs
public sealed class ApplicationServiceHandler
{
private readonly MethodInfo _method;
private readonly object[] _args;
public ApplicationServiceHandler(MethodInfo method, object[] args)
{
Contract.Requires(method != null);
Contract.Requires(args != null);
_method = method;
_args = args;
}
public void Invoke()
{
_method.Invoke(null, _args);
}
[ContractInvariantMethod]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Required for code contracts.")]
private void ObjectInvariant()
{
Contract.Invariant(_method != null);
Contract.Invariant(_args != null);
}
}
ApplicationServiceProvider.cs
public sealed class ApplicationServiceProvider
{
private readonly IEnumerable<Assembly> _assemblies;
private readonly Dictionary<Type, object> _instances;
public ApplicationServiceProvider(IEnumerable<Assembly> assemblies)
{
Contract.Requires(assemblies != null);
_assemblies = assemblies;
_instances = new Dictionary<Type, object>();
}
public static ApplicationServiceProvider CreateDefaultProvider()
{
Contract.Ensures(Contract.Result<ApplicationServiceProvider>() != null);
return new ApplicationServiceProvider(PackageLoader.ReferencedAssemblies);
}
public void Distribute()
{
foreach (var handler in GetHandlers())
{
Contract.Assume(handler != null);
handler.Invoke();
}
}
public IEnumerable<ApplicationServiceHandler> GetHandlers()
{
Contract.Ensures(Contract.Result<IEnumerable<ApplicationServiceHandler>>() != null);
if (_instances.Count == 0)
{
yield break;
}
foreach (var asm in _assemblies)
{
IEnumerable<MethodInfo> methods = GetMethods(asm);
foreach (var method in methods)
{
ParameterInfo[] #params = method.GetParameters();
if (#params.Length > 0)
{
int instanceCount = 0;
object[] args = new object[#params.Length];
for (int i = 0; i < #params.Length; i++)
{
ParameterInfo param = #params[i];
var instance = GetInstance(param);
if (instance != null)
{
instanceCount++;
args[i] = instance;
}
}
if (instanceCount > 0)
{
yield return new ApplicationServiceHandler(method, args);
}
}
}
}
}
public bool RegisterInstance(object instance)
{
Contract.Requires(instance != null);
return AddInstance(instance);
}
private static ApplicationServiceHandlerAttribute GetApplicationServiceHandlerAttribute(MethodInfo method)
{
ApplicationServiceHandlerAttribute attribute = null;
try
{
attribute = method.GetCustomAttribute<ApplicationServiceHandlerAttribute>(false);
}
catch (TypeLoadException)
{
// We don't need to do anything here for now.
}
return attribute;
}
private static IEnumerable<Type> GetDefinedTypes(Assembly assembly)
{
Contract.Requires(assembly != null);
Contract.Ensures(Contract.Result<IEnumerable<Type>>() != null);
try
{
return assembly.DefinedTypes;
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where(type => type != null);
}
}
/// <summary>
/// Gets the methods that are marked with <see cref="ApplicationServiceHandlerAttribute"/> from the assembly.
/// </summary>
/// <remarks>
/// Eyal Shilony, 21/11/2012.
/// </remarks>
/// <param name="assembly">
/// The assembly.
/// </param>
/// <returns>
/// The methods that are marked with <see cref="ApplicationServiceHandlerAttribute"/> from the assembly.
/// </returns>
private static IEnumerable<MethodInfo> GetMethods(Assembly assembly)
{
Contract.Requires(assembly != null);
Contract.Ensures(Contract.Result<IEnumerable<MethodInfo>>() != null);
const TypeAttributes STATIC_TYPE_ATTRIBUTES = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit;
var methods = (from type in GetDefinedTypes(assembly)
where type.Attributes == STATIC_TYPE_ATTRIBUTES
from method in type.GetMethods().AsParallel()
where GetApplicationServiceHandlerAttribute(method) != null
select method).ToArray();
return methods;
}
private bool AddInstance(object instance)
{
Type type = instance.GetType();
return AddInstance(type, instance);
}
private bool AddInstance(Type type, object instance)
{
if (!_instances.ContainsKey(type))
{
_instances.Add(type, instance);
return true;
}
return false;
}
private object GetInstance(ParameterInfo param)
{
object instance = null;
Type paramType = param.ParameterType;
if (_instances.ContainsKey(paramType))
{
instance = _instances[paramType];
}
else
{
foreach (var type in _instances.Keys.Where(type => type.IsSubclassOf(paramType)))
{
instance = _instances[type];
break;
}
}
return instance;
}
}
i hope , i have understood you correctly.if what you mean is marking a class as dependency with attributes then you can do it by creating custom attribute.following is an example of implementing such an attribute :
public class DependencyAttribute : Attribute
{
public DependencyAttribute()
{
}
//The type of service the attributed class represents
public Type ServiceType { get; set; }
//Optional key to associate with the service
public string Key { get; set; }
public virtual void RegisterService(AttributeInfo<DependencyAttribute> attributeInfo, IContainer container)
{
Type serviceType = attributeInfo.Attribute.ServiceType ?? attributeInfo.DecoratedType;
Containerbuilder builder = new ContainerBuilder();
builder.RegisterType(attributeInfo.DecoratedType).As(serviceType).Keyed(
attributeInfo.Attribute.Key ?? attributeInfo.DecoratedType.FullName);
builder.Update(container)
}
}
then you must find all types marked with this attribute and call the RegisterService method of these attributes.
public class DependencyAttributeRegistrator
{
public DependencyAttributeRegistrator()
{
}
public IEnumerable<AttributeInfo<DependencyAttribute>> FindServices()
{
//replace this line with you'r own
var types = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in types)
{
var attributes = type.GetCustomAttributes(typeof(DependencyAttribute), false);
foreach (DependencyAttribute attribute in attributes)
{
yield return new AttributeInfo<DependencyAttribute> { Attribute = attribute, DecoratedType = type };
}
}
}
public void RegisterServices(IEnumerable<AttributeInfo<DependencyAttribute>> services)
{
foreach (var info in services)
{
//replace following two line with you'r own global container
var builder = new ContainerBuilder();
IContainer container = builder.Build();
info.Attribute.RegisterService(info, container);
}
}
}

Resources