i encoutered problem with unity, i want to use property injection, here is what i had in my code :
config of the container :
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<GTModelContainer, GTModelContainer>(new HttpContextLifetimeManager<GTModelContainer>())
.RegisterType<IUnitOfWork, UnitOfWorkGT>()
.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager())
.RegisterType<ISocieteServices, SocieteServices>() ;
}
SocieteService Class :
public class SocieteServices : ISocieteServices
{
private IUnitOfWork UnitOfWork;
public SocieteServices(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
}
i tried to use property injection (i can't use constructor injection with custom data annotation) and here what i had done :
public class CodeSocieteUniqueAttribute : ValidationAttribute
{
[Dependency]
public ISocieteServices SocieteService {get; set;}
[InjectionMethod]
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string codeSociete = value as string;
var societe = SocieteService.getSocieteByCode(codeSociete);
if (societe == null) return ValidationResult.Success;
else return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
the problem is that the societeService in CodeSocieteUniqueAttribute class is not injected.
Assuming that your class for registering types is publicly accessible and has a IUnityContainer object, ie:
public static class Resolver
{
public static IUnityContainer Container { get; set; }
public static void RegisterTypes(IUnityContainer container)
{
// type registrations here
container.RegisterType<GTModelContainer, GTModelContainer>(new HttpContextLifetimeManager<GTModelContainer>())
.RegisterType<IUnitOfWork, UnitOfWorkGT>()
.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager())
.RegisterType<ISocieteServices, SocieteServices>() ;
// Now, set the container
Container = container;
}
}
You could access the container you've built up and resolve these types during method execution.
For instance,
public class CodeSocieteUniqueAttribute : ValidationAttribute
{
[Dependency]
public ISocieteServices SocieteService { get; set; }
[InjectionMethod]
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var societeServices = Resolver.Container.Resolve<ISocieteServices>();
SocieteService = societeServices; // Or, you know, just use this since it's resolved.
string codeSociete = value as string;
var societe = SocieteService.getSocieteByCode(codeSociete);
if (societe == null) return ValidationResult.Success;
else return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
This is actually pretty standard practice, and this MSDN article describes resolving items during runtime.
Another option is to pop the resolution into a default constructor like this:
public class CodeSocieteUniqueAttribute : ValidationAttribute
{
[Dependency]
public ISocieteServices SocieteService {get; set;}
public CodeSocieteUniqueAttribute()
{
var societeServices = Resolver.Container.Resolve<ISocieteServices>();
SocieteService = societeServices;
}
// the rest of the class omitted for brevity
}
Related
I am using automapper to map expressions between classes that implement IEnumerable. The base classes look like this:
public abstract class EntityDtoBase<T> : DtoBase<T> where T : EntityDtoBase<T>
{
public virtual int Id { get; set; }
}
public abstract class PersistenceDtoBase<T> : DtoBase<T> where T : PersistenceDtoBase<T>
{
public virtual int Id { get; set; }
}
public abstract class DtoBase<T> : IEnumerable<T> where T : DtoBase<T>
{
private readonly IList<T> _items;
public int Count => _items.Count;
protected DtoBase()
{
this._items = new List<T>();
}
public void Add(T item)
{
_items.Add(item);
}
/* other methods like AddRange... */
IEnumerator IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return _items.GetEnumerator();
}
}
After migrating to Automapper 10, expression mapping between classes enheriting from EntityDtoBase and PersistenceDtoBase throws a System.EntryPointNotFoundException : Entry point was not found. The configuration I am using in my project is similar to the one used in this unit test:
public class UserEntityDto : EntityDtoBase<UserEntityDto> { }
public class UserPersistenceDto : PersistenceDtoBase<UserPersistenceDto> { }
public class UserProfile : Profile
{
public UserProfile() { CreateMap<UserEntityDto, UserPersistenceDto>().ReverseMap(); }
}
public class UnitTest
{
private readonly IMapper _mapper;
public UnitTest()
{
var sp = CreateServices();
_mapper = sp.GetRequiredService<IMapper>();
}
private static IServiceProvider CreateServices()
{
return new ServiceCollection()
.AddAutoMapper(cfg =>
{
cfg.AddExpressionMapping();
cfg.AddCollectionMappers();
cfg.ForAllMaps((map, exp) => exp.MaxDepth(1));
cfg.AllowNullCollections = true;
cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
}, typeof(UnitTest).Assembly)
.BuildServiceProvider(false);
}
[Fact]
public void Should_Map_Expression()
{
Expression<Func<UserEntityDto, bool>> searchExpression = u => u.Id == 1;
var searchExpressionMapped = _mapper.Map<Expression<Func<UserPersistenceDto, bool>>>(searchExpression);
Assert.NotNull(searchExpressionMapped);
}
You can find the complete unit test project here. The test succeeds using Automapper 9 and fails using Automapper 10.
My service uses a utility class and that utility class has several public properties. Is there something special I need call to ensure these public properties are setup?
The service uses a ASP.NET host. Inside of Global.ASAX I have declared a new AppHostBase:
public class MyServiceHost : AppHostBase
{
public MyServiceHost() : base("My Service Host", typeof(ServiceLibrary).Assembly) {}
public override void Configure(Funq.Container container)
{
container.Register<IDbConnectionFactory>(dbConFactory);
container.RegisterAutoWired<UtilityLibrary>();
container.RegisterAutoWired<RepositoryLibrary>();
}
}
Within both my repository library and utility library is a main class. This may class receives the Container and registers more specific utilities and repositories:
public class UtilityLibrary
{
public UtilityLibrary(Funq.Container container)
{
container.RegisterAutoWired<WidgetAActions>();
container.RegisterAutoWired<WidgetBActions>();
}
}
In the example below, WidgetARepository was set in the constructor of the RepositoryLibrary class. The RepositoryLibrary class, which contains the WidgetARepository, was supplied to the Container in the Configure method of the AppHost (first snippet above). Even still, the WidgetARepository (below) is never set:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetA Get(string id)
{
var item = this.WidgetARepository.Get(id);
if (item == null) { return null; }
// Do something else
return item;
}
}
Must I manually call Resolve()? This seems like it would defeat the purpose of injection by doing this.
If you are using wanting to use the Funq Container Autowire IoC outside of the ServiceStack service then you need to call Container.AutoWire yourself to have the container inject the relevant dependencies. This call is made behind the scenes in the ServiceStack request pipeline.
For ServiceStack v4:
HostContext.Container.AutoWire(objectToPopulate);
For ServiceStack v3:
AppHostBase.Instance.Container.AutoWire(objectToPopulate);
I would typically add this call to the construtor method of the object I want populated with the injections. So in your case:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetAActions()
{
// (Substitute with v3 usage if required.)
HostContext.Container.AutoWire(this);
}
...
}
Hope this helps.
Edit: Have you considered having the container inject the corresponding repository to WidgetAActions's constructor?
container.RegisterAutoWired<WidgetAActions>(c => new WidgetAActions(c.Resolve<WidgetARepository>()));
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; private set; }
public WidgetAActions(WidgetARepository repository)
{
WidgetARepository = repository;
}
...
}
Edit: Or you could resolve and set the public property of your object to the repository and then you don't have to have a constructor:
container.RegisterAutoWired<WidgetAActions>(c =>
new WidgetAActions { WidgetARepository = c.Resolve<WidgetARepository>() }
);
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}
Or you could call autowire at time of resolving WidgetAActions:
container.RegisterAutoWired<WidgetAActions>(c => {
var actions = new WidgetAActions();
container.AutoWire(actions); // All dependencies injected
return actions;
});
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}
I was playin' around with ServiceStack and was wondering if it supported this scenario. I'm using generics in my request types so that many DTOs that inherit from a common interface will support the same basic methods [ like... GetById(int Id) ].
Using a request type specific to a single kind of DTO works, but breaks the generics nice-ness...
var fetchedPerson = client.Get<PersonDto>(new PersonDtoGetById() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson.Id)); //PASS
Mapping a route to the generic also works:
Routes.Add<DtoGetById<PersonDto>>("/persons/{Id}", ApplyTo.Get);
...
var fetchedPerson2 = client.Get<PersonDto>(string.Format("/persons/{0}", person.Id));
Assert.That(person.Id, Is.EqualTo(fetchedPerson2.Id)); //PASS
But using the end-to-end generic request type fails:
var fetchedPerson3 = client.Get<PersonDto>(new DtoGetById<PersonDto>() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson3.Id)); //FAIL
I wonder if I'm just missing something, or if i'm trying to abstract just ooone layer too far... :)
Below is a complete, failing program using NUnit, default ServiceStack stuff:
namespace ssgenerics
{
using NUnit.Framework;
using ServiceStack.ServiceClient.Web;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface;
using ServiceStack.WebHost.Endpoints;
[TestFixture]
class Program
{
public static PersonDto GetNewTestPersonDto()
{
return new PersonDto()
{
Id = 123,
Name = "Joe Blow",
Occupation = "Software Developer"
};
}
static void Main(string[] args)
{}
[Test]
public void TestPutGet()
{
var listeningOn = "http://*:1337/";
var appHost = new AppHost();
appHost.Init();
appHost.Start(listeningOn);
try
{
var BaseUri = "http://localhost:1337/";
var client = new JsvServiceClient(BaseUri);
var person = GetNewTestPersonDto();
client.Put(person);
var fetchedPerson = client.Get<PersonDto>(new PersonDtoGetById() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson.Id));
var fetchedPerson2 = client.Get<PersonDto>(string.Format("/persons/{0}", person.Id));
Assert.That(person.Id, Is.EqualTo(fetchedPerson2.Id));
Assert.That(person.Name, Is.EqualTo(fetchedPerson2.Name));
Assert.That(person.Occupation, Is.EqualTo(fetchedPerson2.Occupation));
var fetchedPerson3 = client.Get<PersonDto>(new DtoGetById<PersonDto>() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson3.Id));
Assert.That(person.Name, Is.EqualTo(fetchedPerson3.Name));
Assert.That(person.Occupation, Is.EqualTo(fetchedPerson3.Occupation));
}
finally
{
appHost.Stop();
}
}
}
public interface IDto : IReturnVoid
{
int Id { get; set; }
}
public class PersonDto : IDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Occupation { get; set; }
}
public class DtoGetById<T> : IReturn<T> where T : IDto { public int Id { get; set; } }
public class PersonDtoGetById : IReturn<PersonDto> { public int Id { get; set; } }
public abstract class DtoService<T> : Service where T : IDto
{
public abstract T Get(DtoGetById<T> Id);
public abstract void Put(T putter);
}
public class PersonService : DtoService<PersonDto>
{
public override PersonDto Get(DtoGetById<PersonDto> Id)
{
//--would retrieve from data persistence layer
return Program.GetNewTestPersonDto();
}
public PersonDto Get(PersonDtoGetById Id)
{
return Program.GetNewTestPersonDto();
}
public override void Put(PersonDto putter)
{
//--would persist to data persistence layer
}
}
public class AppHost : AppHostHttpListenerBase
{
public AppHost()
: base("Test HttpListener",
typeof(PersonService).Assembly
) { }
public override void Configure(Funq.Container container)
{
Routes.Add<DtoGetById<PersonDto>>("/persons/{Id}", ApplyTo.Get);
}
}
}
No, It's a fundamental concept in ServiceStack that each Service requires its own unique Request DTO, see this answer for more examples on this.
You could do:
[Route("/persons/{Id}", "GET")]
public class Persons : DtoGetById<Person> { ... }
But I strongly advise against using inheritance in DTOs. Property declaration is like a DSL for a service contract and its not something that should be hidden.
For more details see this answer on the purpose of DTO's in Services.
Seeing a strange problem, getting empty metata pages for xml,json and jvs.
Using the following command line app. How does one debug these issues?
namespace ConsoleApplication2
{
public struct NativeUser
{
public int login;
public string group;
public string name;
}
[DataContract]
public class User
{
private NativeUser _native;
public User() { }
public User(NativeUser native)
{
_native = native;
}
public static implicit operator NativeUser(User user)
{
return user._native;
}
public static implicit operator User(NativeUser native)
{
return new User(native);
}
// ReSharper disable InconsistentNaming
[DataMember]
public int login
{
get { return _native.login; }
set { _native.login = value; }
}
[DataMember]
public string group
{
get { return _native.group; }
set { _native.group = value; }
}
[DataMember]
public string name
{
get { return _native.name; }
set { _native.name = value; }
}
}
[Description("GET account, all or by list of groups or by list of logins")]
[Route("/accounts/{groups}", "GET")]
[Route("/accounts/{logins}", "GET")]
[Route("/accounts/", "GET")]
public class Accounts : IReturn<User[]>
{
public string[] groups { set; get; }
public int[] logins { set; get; }
public Accounts() { }
public Accounts(params int[] logins)
{
this.logins = logins;
}
public Accounts(params string[] groups)
{
this.groups = groups;
}
}
public class Host : AppHostHttpListenerBase
{
public Host() : base("Test",
typeof(Accounts).Assembly)
{
}
public override void Configure(Funq.Container container)
{
}
}
public class Servce : IService
{
public object Get(Accounts request)
{
return new List<User>(){new User(new NativeUser())};
}
}
class Program
{
static void Main(string[] args)
{
var host = new Host();
host.Init();
host.Start("http://+:12345/");
global::System.Console.ReadLine();
}
}
}
Nm, found the bug :
public class Accounts : IReturn<User[]>
needs to be
public class Accounts : IReturn<List<User>>
Another very note worthy thing: All DTO's and objects being passed back and fourth in the DTO's require an empty constructor in order for the metata data to be properly generated.
Not sure if this is by design or a bug
is there any problem with this kinda registration via structure map??
static public class ContainerBootstrapper
{
static public void BootstrapDefaultContainer(bool test = false)
{
StructureMap.ObjectFactory.Initialize(x =>
{
x.Scan(p =>
{
p.AssemblyContainingType<IPropertyType>();
p.AddAllTypesOf<IPropertyType>();
// p.AddAllTypesOf<IPropertyType>().NameBy(c => c.Name);
});
});
}
public interface IPropertyType : IIdentityObject, IPriority
{
string PropertyName { get; set; }
ObjectType ObjectType { get; }
string DisplayName { get; set; }
IEntityType EntityType { get; set; }
IList<IPropertyRuleObject> RuleObjects { get; set; }
void AddRuleObject(IPropertyRuleObject ruleObject);
}
public abstract class PropertyTypeBase : PersistentObject, IPropertyType
{
public PropertyTypeBase()
{
}
public PropertyTypeBase(string propertyName, string displayName)
{
PropertyName = propertyName;
DisplayName = displayName;
}
....
}
public class StringType : PropertyTypeBase
{
private ObjectType _objectType;
public StringType()
{
_objectType = new ObjectType(typeof(string));
}
public StringType(string propertyName, string displayName)
: base()
{
PropertyName = propertyName;
DisplayName = displayName;
}
public override ObjectType ObjectType
{
get { return _objectType; }
}
}
when ContainerBootstrapper.BootstrapDefaultContainer(); execute I see this line of error:
StructureMap Exception Code: 200
Could not find an Instance named "StringType" for PluginType Azarakhsh.Domain.Core.AdaptiveObjectModel.Interface.IPropertyType
the calling code:
public IPropertyType GetPropertyType(IIdentityObject identityObject, string name)
{
string[] Properties = name.Split('.');
object Result = identityObject;
foreach (var Property in Properties)
Result = Result.GetType().GetProperty(Property).PropertyType.Name;
IPropertyType propertyType = StructureMap.ObjectFactory.GetNamedInstance<IPropertyType> (Result + "Type");
if (propertyType==null)
throw new Exception("Property type not found");
return propertyType;
}
what is the problem?
You are trying to get a named instance, but from what I can see of the code you have provided, you dont name your instances. The line of code that name your instances is commented out.
But even if you would just use the ObjectFactory.GetInstance<IPropertyType>(); here, you would have got an error because structuremap dont know what constructor to use. There are several solutions to theis problem.
Change your design so you only have one constructor
Mark your default constructor with the [DefaultConstructor] attribute, then it will work.
You can register it with objectFactory manually with something like this:
x.For().Use().Ctor("propertyName").Is("someValue").Ctor("displayName").Is("someValue");
You can write a custom registrationconvention as described here