Unity to Structuremap help - structuremap

I am trying to convert this code in my DI mapping from Unity to Structuremap but I cannot seem to get it to work. I am using Repository pattern like the one in found in shrinkr by Kazi Manzur Rashid found here http://shrinkr.codeplex.com/ Any help would be appreciated!
Unity Code:
....
private static readonly Func<LifetimeManager> perRequest = () => new PerRequestLifetimeManager();
....
IBuildManager buildManager = container.Resolve<IBuildManager>(); RegisterRepositories(buildManager, container);
....
private static void RegisterRepositories(IBuildManager buildManager, IUnityContainer container)
{
Type genericRepositoryType = typeof(IRepository<>);
IEnumerable<Type> repositoryContractTypes = buildManager.PublicTypes.Where(type => (type != null) && type.IsInterface && type.GetInterfaces().Any(interfaceType => interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition().Equals(genericRepositoryType))).ToList();
foreach (Type repositoryImplementationType in buildManager.ConcreteTypes.Where(implementationType => repositoryContractTypes.Any(contractType => contractType.IsAssignableFrom(implementationType))))
{
foreach (Type repositoryInterfaceType in repositoryImplementationType.GetInterfaces())
{
container.RegisterType(repositoryInterfaceType, repositoryImplementationType, perRequest());
}
}
}

I don't know Unity, but I'm guessing you are trying to make requests for IRepository return a ProductRepository.
In StructureMap, the code is a bit simpler:
var container = new Container(x => {
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
});
});

Related

Error : The requested service 'Microsoft.Owin.IOwinContext' has not been registered

I am working in getting connectionstring with owin startup for tenant .I have MultiTenantOwinMiddleware to process Tenant.I have following code in my Startup class.
I am beginner with Owin.
builder.RegisterType<OwnerDbContext>()
.AsSelf()
.WithParameter(new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof (string) && pi.Name == "ConnectionString",
(pi, ctx) => GetTenantConnectionString(ctx)))
.InstancePerRequest();
private static string GetTenantConnectionString(IComponentContext ctx)
{
var owinContext = ctx.Resolve<IOwinContext>();
var tenant = owinContext.GetCurrentTenant<OwnerTenant>();
return tenant != null ? tenant.ConnectionString : "XYZ";
}
I am getting this error .
The requested service 'Microsoft.Owin.IOwinContext' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
Edit
public static void ConfigureIoCContainer(this IAppBuilder app, HttpConfiguration config)
{
var container = RegisterInstances(); // Function for component registration
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.UseAutofacMiddleware(container);
app.Use(async (ctx, next) =>
{
using (var scope = container.BeginLifetimeScope(b => b.RegisterInstance(ctx).As<IOwinContext>()))
{
ctx.Set<ILifetimeScope>("idsrv:AutofacScope", scope);
await next();
}
});
}
Any any help would be appreciated.
Thank you very much

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.

Use ConstructedBy together with the non-generic For

I have this registration in StructureMap
ObjectFactory.Initialize(x => {
x.For<IPageModel>().UseSpecial(y => y.ConstructedBy( r => ((MvcHandler) HttpContext.Current.Handler).RequestContext.RouteData.GetCurrentModel<IPageModel>()));
});
And then I access this object in my constructor like this
public HomeController(IPageModel model) {}
Now I would like to register all concrete types that implements the interface IPageModel and when asked for I want to use the same For<> statement to get the correct instance.
It seems like i could use Scan together with my own convention to do this but I can't figure out exactly how to do it.
This is some example code
x.Scan(scanner =>
{
scanner.AssembliesFromApplicationBaseDirectory();
scanner.Convention<MySpecialConvetion>();
});
public class MySpecialConvetion : IRegistrationConvention {
public void Process(Type type, Registry registry) {
if(type.IsAssignableFrom(typeof(IPageModel))) {
registry.For<CONCRETE IMPLEMENTATION>().UseSpecial(y => y.ConstructedBy( r => ((MvcHandler) HttpContext.Current.Handler).RequestContext.RouteData.GetCurrentModel<CONCRETE IMPLEMENTATION>()));
}
}
}
Edit: It seems like I need to use the non-generic For, but how can I handle the construction my self using the non-generic For?
I got this working by creating a generic method definition, and used reflection to populate the types. Easier to show than explain:
public class MySpecialConvetion : IRegistrationConvention
{
public static readonly MethodInfo RegisterMethod = typeof (MySpecialConvetion)
.GetMethod("Register", BindingFlags.NonPublic | BindingFlags.Static)
.GetGenericMethodDefinition();
public void Process(Type type, Registry registry)
{
if (type.IsAssignableFrom(typeof (IPageModel)))
{
var specificRegisterMethod = RegisterMethod.MakeGenericMethod(new[] { type });
specificRegisterMethod.Invoke(null, new object[] { registry });
}
}
static private void Register<T>(Registry registry)
where T : IPageModel
{
registry
.For<T>()
.UseSpecial(y => y.ConstructedBy(r => GetCurrentPageModel<T>()));
}
static private T GetCurrentPageModel<T>()
where T : IPageModel
{
var handler = (MvcHandler) HttpContext.Current.Handler;
if (handler == null)
return default(T);
return handler.RequestContext.RouteData.GetCurrentModel<T>();
}
}
I added an intermediate step and checked for a null handler since I didn't have one in my site. But this should get you the missing piece you needed.

How can I use Ninject in my ASP MVC MSpec tests?

I'm trying to write an MSpec test that instantiates one of my controllers with all the correct Ninject bindings. How do I go about doing that? This is what I have so far:
[Subject(Concern.Initialization)]
public class when_permanent_employee_page_is_loaded_for_first_time
{
private static PermanentEmployeeController controller;
Establish context = () =>
{
NinjectControllerFactory controllerFactory = new NinjectControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
controller = (PermanentEmployeeController)controllerFactory.CreateController(new RequestContext(), "PermanentEmployee");
};
private Because of = () => controller.Index();
private It should_load_all_available_jobs = () =>
{
var blah = controller;
var blah3 = 3;
};
It should_load_all_available_locations;
It should_load_all_available_departments;
}
In the above code I'm simply trying to see if I can instantiate my controller with all the Ninject bindings in tact. The NinjectControllerFactory class looks like this:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new DefaultModule());
public IKernel Kernel
{
get
{
return kernel;
}
set
{
this.kernel = value;
}
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return null;
}
return (IController)kernel.Get(controllerType);
}
}
And the DefaultModule class like this:
public class DefaultModule : NinjectModule
{
/// <summary>
/// Performs the binding of interfaces to their respective implementations. 'Tis very cool.
/// </summary>
public override void Load()
{
// Data service bindings
Bind<IJobService>().To<JobServiceImpl>().InTransientScope();
Bind<IJobWsWrapper>().To<JobWsWrapperImpl>().InTransientScope();
// View model factory bindings
Bind<IPermanentEmployeeViewModelFactory>().To<PermanentEmployeeViewModelFactoryImpl>().InTransientScope();
}
}
So my question is: is there a way to specify the bindings of my Ninject module in my MSpec test and then have my instantiated controller use those bindings? I want to avoid instantiating my Controller like this: var controller = new Controller() since that doesn't allow me to test the Ninject bindings. I've also looked into the TestControllerBuilder class from the MvcContrib library but I haven't figured out how to instantiate controllers with Ninject bindings with it. Thanks for the help!
Ok I figured out how to initialize my controller along with the Ninject Bindings in my MSpec tests! Well I didn't figure it out. A coworker did but that's irrelevant now. Here is how it's done:
public class when_permanent_employee_page_is_loaded_for_first_time
{
private static Mock<IJobService> jobServiceMock;
private static Mock<IUtilsService> utilsServiceMock;
private static PermanentEmployeeController controller;
private static ContextMocks mocks;
private static IList<Job> jobs = new List<Job>();
private static IList<string> departments = new List<string>();
private static IList<string> locations = new List<string>();
private static PermanentEmployeeJobsViewModel viewModel;
Establish context = () =>
{
jobServiceMock = new Mock<IJobService>();
jobServiceMock.Setup(x => x.GetJobs(1)).Returns(jobs);
jobServiceMock.Setup(x => x.GetDepartmentsFromJobs(jobs)).Returns(departments);
jobServiceMock.Setup(x => x.GetLocationsFromJobs(jobs)).Returns(locations);
utilsServiceMock = new Mock<IUtilsService>();
var kernel = new StandardKernel(new DefaultModule());
kernel.Rebind<IJobService>().ToConstant(jobServiceMock.Object);
kernel.Rebind<IUtilsService>().ToConstant(utilsServiceMock.Object);
controller = kernel.Get<PermanentEmployeeController>();
mocks = new ContextMocks(controller);
};
Because of = () =>
{
PartialViewResult view = (PartialViewResult)controller.Index();
viewModel = (PermanentEmployeeJobsViewModel)view.ViewData.Model;
};
It should_load_all_available_jobs = () =>
{
jobServiceMock.Verify(x => x.GetJobs(1));
jobServiceMock.Verify(x => x.GetDepartmentsFromJobs(jobs));
jobServiceMock.Verify(x => x.GetLocationsFromJobs(jobs));
viewModel.Departments.ShouldEqual(departments);
};
It should_load_all_available_locations;
It should_load_all_available_departments;
}
Ok that's it :). Hopefully someone else can benefit from this answer. Special thanks to my coworker for figuring this out. You know who you are :D

is it ok to use StructureMap like this? asp.net MVC 3

i have a doubt that i am not using the best practice for using Structure-Map.
all working fine but just a confusion in mind.
my code look like this.
global.asax
IContainer container = new Container(
x => {
x.For<IUserRepo>().Use<UserRepo>();
x.For<IPostRepo>().Use<PostRepo>(); // this is the soultion for the error
});
DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
PostController
private readonly IPostRepo _postRepo;
public PostController(IPostRepo postRepo)
{
this._postRepo = postRepo;
}
StructureMapDependencyResolver
public class StructureMapDependencyResolver : IDependencyResolver
{
private readonly IContainer _container;
public StructureMapDependencyResolver(IContainer container )
{
this._container = container;
}
public object GetService(Type serviceType)
{
object instance = _container.TryGetInstance(serviceType);
if(instance == null && !serviceType.IsAbstract)
{
_container.Configure(c => c.AddType(serviceType,serviceType));
instance = _container.TryGetInstance(serviceType);
}
return instance;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances(serviceType).Cast<object>();
}
}
here is the IPostRepo looks like
public interface IPostRepo
{
bool CreatePost(Post newPost);
List<Post> ShowAllPosts();
Post FindPostById(int postId);
Post EditPost(Post editPost);
UserPostCommentViewModel FindAllPostComments(int postId);
int? AddPlusOneToNumberOfViews(int postId);
}
thx martin for your help
No. Like I said in your other question, take out the Controller Activator ... unless you are using it for a purpose (which it doesn't seem like you are).
Also, this line is plain WRONG:
x.ForRequestedType<AccountController>().TheDefault.Is.
ConstructedBy(() => new AccountController(new UserRepo()));
You should not be using new for your UserRepo ... that is what the line above is taking care of:
x.For<IUserRepo>().Use<UserRepo>();
If you take out the ControllerActivator, you should have a nice start to an MVC app.

Resources