How to get Simple injector to auto resolve interface when it only has one concrete?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
Currently i have a webapi controller with the constructor like this:
readonly IQueryFactory queryFactory;
readonly ICommandFactory commandFactory;
public UserBenefitsController(
IQueryFactory queryFactory,
ICommandFactory commandFactory)
{
this.queryFactory = queryFactory;
this.commandFactory = commandFactory;
}
I am using simple injector to register both of these types.
container.RegisterWebApiRequest<IQueryFactory, QueryFactory>();
container.RegisterWebApiRequest<ICommandFactory, CommandFactory>();
But i am finding that as i continue to develop my app that I am continuing to have a lot of ISomeInterface
resolving to ISomeConcrete
with 1:1 ratio.
Is it possible to tell simple injector to look for at an interface and automatically resolve it when there is only 1 concrete for it within the WebApiRequest scope?
c# asp.net-web-api simple-injector
add a comment |
Currently i have a webapi controller with the constructor like this:
readonly IQueryFactory queryFactory;
readonly ICommandFactory commandFactory;
public UserBenefitsController(
IQueryFactory queryFactory,
ICommandFactory commandFactory)
{
this.queryFactory = queryFactory;
this.commandFactory = commandFactory;
}
I am using simple injector to register both of these types.
container.RegisterWebApiRequest<IQueryFactory, QueryFactory>();
container.RegisterWebApiRequest<ICommandFactory, CommandFactory>();
But i am finding that as i continue to develop my app that I am continuing to have a lot of ISomeInterface
resolving to ISomeConcrete
with 1:1 ratio.
Is it possible to tell simple injector to look for at an interface and automatically resolve it when there is only 1 concrete for it within the WebApiRequest scope?
c# asp.net-web-api simple-injector
add a comment |
Currently i have a webapi controller with the constructor like this:
readonly IQueryFactory queryFactory;
readonly ICommandFactory commandFactory;
public UserBenefitsController(
IQueryFactory queryFactory,
ICommandFactory commandFactory)
{
this.queryFactory = queryFactory;
this.commandFactory = commandFactory;
}
I am using simple injector to register both of these types.
container.RegisterWebApiRequest<IQueryFactory, QueryFactory>();
container.RegisterWebApiRequest<ICommandFactory, CommandFactory>();
But i am finding that as i continue to develop my app that I am continuing to have a lot of ISomeInterface
resolving to ISomeConcrete
with 1:1 ratio.
Is it possible to tell simple injector to look for at an interface and automatically resolve it when there is only 1 concrete for it within the WebApiRequest scope?
c# asp.net-web-api simple-injector
Currently i have a webapi controller with the constructor like this:
readonly IQueryFactory queryFactory;
readonly ICommandFactory commandFactory;
public UserBenefitsController(
IQueryFactory queryFactory,
ICommandFactory commandFactory)
{
this.queryFactory = queryFactory;
this.commandFactory = commandFactory;
}
I am using simple injector to register both of these types.
container.RegisterWebApiRequest<IQueryFactory, QueryFactory>();
container.RegisterWebApiRequest<ICommandFactory, CommandFactory>();
But i am finding that as i continue to develop my app that I am continuing to have a lot of ISomeInterface
resolving to ISomeConcrete
with 1:1 ratio.
Is it possible to tell simple injector to look for at an interface and automatically resolve it when there is only 1 concrete for it within the WebApiRequest scope?
c# asp.net-web-api simple-injector
c# asp.net-web-api simple-injector
edited Nov 14 '14 at 18:56
qujck
12k42964
12k42964
asked Nov 14 '14 at 16:17
4imble4imble
8,1071355109
8,1071355109
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You can use batch / automatic registration to resolve to concrete instances.
The Simple Injector documentation explains it here
For instance:
ScopedLifestyle scopedLifestyle = new WebApiRequestLifestyle();
var assembly = typeof(YourRepository).Assembly;
var registrations =
from type in assembly.GetExportedTypes()
where type.Namespace == "Acme.YourRepositories"
where type.GetInterfaces().Any()
select new
{
Service = type.GetInterfaces().Single(),
Implementation = type
};
foreach (var reg in registrations)
container.Register(reg.Service, reg.Implementation, scopedLifestyle);
I get an "Sequence contains more than one element" exception when I do this in the section.
– pmbanugo
Apr 28 '16 at 13:42
I've used the second answer to this question to resolve my problem. Thanks
– pmbanugo
Apr 28 '16 at 13:57
add a comment |
Besides the correct (and probably preferable) answer of Mr Bacardi, you can also achieve this using unregistered type resolution, using the following extension method:
public static void AutoMap(this Container container, params Assembly assemblies) {
container.ResolveUnregisteredType += (s, e) => {
if (e.UnregisteredServiceType.IsInterface && !e.Handled) {
Type concreteTypes = (
from assembly in assemblies
from type in assembly.GetTypes()
where !type.IsAbstract && !type.IsGenericType
where e.UnregisteredServiceType.IsAssignableFrom(type)
select type)
.ToArray();
if (concreteTypes.Length == 1) {
e.Register(Lifestyle.Transient.CreateRegistration(concreteTypes[0],
container));
}
}
};
}
You can use this extension method as follows:
container.AutoMap(Assembly.GetExecutingAssembly());
It is important that you apply a strict set of assemblies to this method, containing only the production assemblies. When you apply all AppDomain assemblies, you'll find that it is likely to fail in your integration or unit test suite, since you will likely have fake implementations of those interfaces in those assemblies.
My preference though is to do as much explicit up front registration as possible, which is the solution that Mr Bacardi describes. The method described here uses a 'just in time' approach, where it starts to look for an implementation on the first resolve. If you call container.Verify()
however, you will be safe in most cases, although it is possible that a call to Verify() succeeds, while resolving object graphs fails as runtime, because Verify() will only verify objects that are known to the configuration. So you will have to make sure that your unregistered interfaces are directly or indirectly referenced by something that actually is registered. Since it is easy to overlook such thing, I prefer Mr Barardi's approach.
But I must admit that in the applications I work on (which are usually quite big), we have just a few of those 'one-to-one' implementations. Most implementations in the system implement a generic interface (such as this and this) and there's hardly ever a reason for me to do batch registration on those non-generic interfaces. Simple Injector on the other hand has great support for batch registering generic interfaces using the Register
methods.
Excellent information, many thanks for taking the time to give an alternative.
– 4imble
Nov 17 '14 at 8:59
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26934325%2fhow-to-get-simple-injector-to-auto-resolve-interface-when-it-only-has-one-concre%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use batch / automatic registration to resolve to concrete instances.
The Simple Injector documentation explains it here
For instance:
ScopedLifestyle scopedLifestyle = new WebApiRequestLifestyle();
var assembly = typeof(YourRepository).Assembly;
var registrations =
from type in assembly.GetExportedTypes()
where type.Namespace == "Acme.YourRepositories"
where type.GetInterfaces().Any()
select new
{
Service = type.GetInterfaces().Single(),
Implementation = type
};
foreach (var reg in registrations)
container.Register(reg.Service, reg.Implementation, scopedLifestyle);
I get an "Sequence contains more than one element" exception when I do this in the section.
– pmbanugo
Apr 28 '16 at 13:42
I've used the second answer to this question to resolve my problem. Thanks
– pmbanugo
Apr 28 '16 at 13:57
add a comment |
You can use batch / automatic registration to resolve to concrete instances.
The Simple Injector documentation explains it here
For instance:
ScopedLifestyle scopedLifestyle = new WebApiRequestLifestyle();
var assembly = typeof(YourRepository).Assembly;
var registrations =
from type in assembly.GetExportedTypes()
where type.Namespace == "Acme.YourRepositories"
where type.GetInterfaces().Any()
select new
{
Service = type.GetInterfaces().Single(),
Implementation = type
};
foreach (var reg in registrations)
container.Register(reg.Service, reg.Implementation, scopedLifestyle);
I get an "Sequence contains more than one element" exception when I do this in the section.
– pmbanugo
Apr 28 '16 at 13:42
I've used the second answer to this question to resolve my problem. Thanks
– pmbanugo
Apr 28 '16 at 13:57
add a comment |
You can use batch / automatic registration to resolve to concrete instances.
The Simple Injector documentation explains it here
For instance:
ScopedLifestyle scopedLifestyle = new WebApiRequestLifestyle();
var assembly = typeof(YourRepository).Assembly;
var registrations =
from type in assembly.GetExportedTypes()
where type.Namespace == "Acme.YourRepositories"
where type.GetInterfaces().Any()
select new
{
Service = type.GetInterfaces().Single(),
Implementation = type
};
foreach (var reg in registrations)
container.Register(reg.Service, reg.Implementation, scopedLifestyle);
You can use batch / automatic registration to resolve to concrete instances.
The Simple Injector documentation explains it here
For instance:
ScopedLifestyle scopedLifestyle = new WebApiRequestLifestyle();
var assembly = typeof(YourRepository).Assembly;
var registrations =
from type in assembly.GetExportedTypes()
where type.Namespace == "Acme.YourRepositories"
where type.GetInterfaces().Any()
select new
{
Service = type.GetInterfaces().Single(),
Implementation = type
};
foreach (var reg in registrations)
container.Register(reg.Service, reg.Implementation, scopedLifestyle);
edited Nov 16 '14 at 12:20
Steven
129k17224342
129k17224342
answered Nov 14 '14 at 16:59
Mr BacardiMr Bacardi
761
761
I get an "Sequence contains more than one element" exception when I do this in the section.
– pmbanugo
Apr 28 '16 at 13:42
I've used the second answer to this question to resolve my problem. Thanks
– pmbanugo
Apr 28 '16 at 13:57
add a comment |
I get an "Sequence contains more than one element" exception when I do this in the section.
– pmbanugo
Apr 28 '16 at 13:42
I've used the second answer to this question to resolve my problem. Thanks
– pmbanugo
Apr 28 '16 at 13:57
I get an "Sequence contains more than one element" exception when I do this in the section.
– pmbanugo
Apr 28 '16 at 13:42
I get an "Sequence contains more than one element" exception when I do this in the section.
– pmbanugo
Apr 28 '16 at 13:42
I've used the second answer to this question to resolve my problem. Thanks
– pmbanugo
Apr 28 '16 at 13:57
I've used the second answer to this question to resolve my problem. Thanks
– pmbanugo
Apr 28 '16 at 13:57
add a comment |
Besides the correct (and probably preferable) answer of Mr Bacardi, you can also achieve this using unregistered type resolution, using the following extension method:
public static void AutoMap(this Container container, params Assembly assemblies) {
container.ResolveUnregisteredType += (s, e) => {
if (e.UnregisteredServiceType.IsInterface && !e.Handled) {
Type concreteTypes = (
from assembly in assemblies
from type in assembly.GetTypes()
where !type.IsAbstract && !type.IsGenericType
where e.UnregisteredServiceType.IsAssignableFrom(type)
select type)
.ToArray();
if (concreteTypes.Length == 1) {
e.Register(Lifestyle.Transient.CreateRegistration(concreteTypes[0],
container));
}
}
};
}
You can use this extension method as follows:
container.AutoMap(Assembly.GetExecutingAssembly());
It is important that you apply a strict set of assemblies to this method, containing only the production assemblies. When you apply all AppDomain assemblies, you'll find that it is likely to fail in your integration or unit test suite, since you will likely have fake implementations of those interfaces in those assemblies.
My preference though is to do as much explicit up front registration as possible, which is the solution that Mr Bacardi describes. The method described here uses a 'just in time' approach, where it starts to look for an implementation on the first resolve. If you call container.Verify()
however, you will be safe in most cases, although it is possible that a call to Verify() succeeds, while resolving object graphs fails as runtime, because Verify() will only verify objects that are known to the configuration. So you will have to make sure that your unregistered interfaces are directly or indirectly referenced by something that actually is registered. Since it is easy to overlook such thing, I prefer Mr Barardi's approach.
But I must admit that in the applications I work on (which are usually quite big), we have just a few of those 'one-to-one' implementations. Most implementations in the system implement a generic interface (such as this and this) and there's hardly ever a reason for me to do batch registration on those non-generic interfaces. Simple Injector on the other hand has great support for batch registering generic interfaces using the Register
methods.
Excellent information, many thanks for taking the time to give an alternative.
– 4imble
Nov 17 '14 at 8:59
add a comment |
Besides the correct (and probably preferable) answer of Mr Bacardi, you can also achieve this using unregistered type resolution, using the following extension method:
public static void AutoMap(this Container container, params Assembly assemblies) {
container.ResolveUnregisteredType += (s, e) => {
if (e.UnregisteredServiceType.IsInterface && !e.Handled) {
Type concreteTypes = (
from assembly in assemblies
from type in assembly.GetTypes()
where !type.IsAbstract && !type.IsGenericType
where e.UnregisteredServiceType.IsAssignableFrom(type)
select type)
.ToArray();
if (concreteTypes.Length == 1) {
e.Register(Lifestyle.Transient.CreateRegistration(concreteTypes[0],
container));
}
}
};
}
You can use this extension method as follows:
container.AutoMap(Assembly.GetExecutingAssembly());
It is important that you apply a strict set of assemblies to this method, containing only the production assemblies. When you apply all AppDomain assemblies, you'll find that it is likely to fail in your integration or unit test suite, since you will likely have fake implementations of those interfaces in those assemblies.
My preference though is to do as much explicit up front registration as possible, which is the solution that Mr Bacardi describes. The method described here uses a 'just in time' approach, where it starts to look for an implementation on the first resolve. If you call container.Verify()
however, you will be safe in most cases, although it is possible that a call to Verify() succeeds, while resolving object graphs fails as runtime, because Verify() will only verify objects that are known to the configuration. So you will have to make sure that your unregistered interfaces are directly or indirectly referenced by something that actually is registered. Since it is easy to overlook such thing, I prefer Mr Barardi's approach.
But I must admit that in the applications I work on (which are usually quite big), we have just a few of those 'one-to-one' implementations. Most implementations in the system implement a generic interface (such as this and this) and there's hardly ever a reason for me to do batch registration on those non-generic interfaces. Simple Injector on the other hand has great support for batch registering generic interfaces using the Register
methods.
Excellent information, many thanks for taking the time to give an alternative.
– 4imble
Nov 17 '14 at 8:59
add a comment |
Besides the correct (and probably preferable) answer of Mr Bacardi, you can also achieve this using unregistered type resolution, using the following extension method:
public static void AutoMap(this Container container, params Assembly assemblies) {
container.ResolveUnregisteredType += (s, e) => {
if (e.UnregisteredServiceType.IsInterface && !e.Handled) {
Type concreteTypes = (
from assembly in assemblies
from type in assembly.GetTypes()
where !type.IsAbstract && !type.IsGenericType
where e.UnregisteredServiceType.IsAssignableFrom(type)
select type)
.ToArray();
if (concreteTypes.Length == 1) {
e.Register(Lifestyle.Transient.CreateRegistration(concreteTypes[0],
container));
}
}
};
}
You can use this extension method as follows:
container.AutoMap(Assembly.GetExecutingAssembly());
It is important that you apply a strict set of assemblies to this method, containing only the production assemblies. When you apply all AppDomain assemblies, you'll find that it is likely to fail in your integration or unit test suite, since you will likely have fake implementations of those interfaces in those assemblies.
My preference though is to do as much explicit up front registration as possible, which is the solution that Mr Bacardi describes. The method described here uses a 'just in time' approach, where it starts to look for an implementation on the first resolve. If you call container.Verify()
however, you will be safe in most cases, although it is possible that a call to Verify() succeeds, while resolving object graphs fails as runtime, because Verify() will only verify objects that are known to the configuration. So you will have to make sure that your unregistered interfaces are directly or indirectly referenced by something that actually is registered. Since it is easy to overlook such thing, I prefer Mr Barardi's approach.
But I must admit that in the applications I work on (which are usually quite big), we have just a few of those 'one-to-one' implementations. Most implementations in the system implement a generic interface (such as this and this) and there's hardly ever a reason for me to do batch registration on those non-generic interfaces. Simple Injector on the other hand has great support for batch registering generic interfaces using the Register
methods.
Besides the correct (and probably preferable) answer of Mr Bacardi, you can also achieve this using unregistered type resolution, using the following extension method:
public static void AutoMap(this Container container, params Assembly assemblies) {
container.ResolveUnregisteredType += (s, e) => {
if (e.UnregisteredServiceType.IsInterface && !e.Handled) {
Type concreteTypes = (
from assembly in assemblies
from type in assembly.GetTypes()
where !type.IsAbstract && !type.IsGenericType
where e.UnregisteredServiceType.IsAssignableFrom(type)
select type)
.ToArray();
if (concreteTypes.Length == 1) {
e.Register(Lifestyle.Transient.CreateRegistration(concreteTypes[0],
container));
}
}
};
}
You can use this extension method as follows:
container.AutoMap(Assembly.GetExecutingAssembly());
It is important that you apply a strict set of assemblies to this method, containing only the production assemblies. When you apply all AppDomain assemblies, you'll find that it is likely to fail in your integration or unit test suite, since you will likely have fake implementations of those interfaces in those assemblies.
My preference though is to do as much explicit up front registration as possible, which is the solution that Mr Bacardi describes. The method described here uses a 'just in time' approach, where it starts to look for an implementation on the first resolve. If you call container.Verify()
however, you will be safe in most cases, although it is possible that a call to Verify() succeeds, while resolving object graphs fails as runtime, because Verify() will only verify objects that are known to the configuration. So you will have to make sure that your unregistered interfaces are directly or indirectly referenced by something that actually is registered. Since it is easy to overlook such thing, I prefer Mr Barardi's approach.
But I must admit that in the applications I work on (which are usually quite big), we have just a few of those 'one-to-one' implementations. Most implementations in the system implement a generic interface (such as this and this) and there's hardly ever a reason for me to do batch registration on those non-generic interfaces. Simple Injector on the other hand has great support for batch registering generic interfaces using the Register
methods.
edited Nov 16 '18 at 15:46
answered Nov 14 '14 at 20:27
StevenSteven
129k17224342
129k17224342
Excellent information, many thanks for taking the time to give an alternative.
– 4imble
Nov 17 '14 at 8:59
add a comment |
Excellent information, many thanks for taking the time to give an alternative.
– 4imble
Nov 17 '14 at 8:59
Excellent information, many thanks for taking the time to give an alternative.
– 4imble
Nov 17 '14 at 8:59
Excellent information, many thanks for taking the time to give an alternative.
– 4imble
Nov 17 '14 at 8:59
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26934325%2fhow-to-get-simple-injector-to-auto-resolve-interface-when-it-only-has-one-concre%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown