I tried to use the new AssertConfigurationIsValid method in Structure Map 3 to validate my automapper configuration. I have:
Strapper.Boot(x => {
x.AddIoc();
});
ObjectFactory.Container.AssertConfigurationIsValid();
The AddIoc method has the following:
ObjectFactory.Initialize(x => { x.AddRegistry(new IocRegistry()); });
DependencyResolver.SetResolver(new IocDependencyResolver(ObjectFactory.Container));
GlobalConfiguration.Configuration.DependencyResolver = new IocDependencyResolver(ObjectFactory.Container);
FilterProviders.Providers.Remove(FilterProviders.Providers.Single(x => x is FilterAttributeFilterProvider));
FilterProviders.Providers.Add(new IocFilterProvider(ObjectFactory.Container));
Where the IocRegistry is the following:
For<ConfigurationStore>().Singleton().Use<ConfigurationStore>().Ctor<IEnumerable<IObjectMapper>>().Is("Mapper Registry", MapperRegistry.AllMappers);
For<IConfigurationProvider>().Use(x => x.GetInstance<ConfigurationStore>());
For<IConfiguration>().Use(x => x.GetInstance<ConfigurationStore>());
For<IOwinContext>().Transient().Use(() => HttpContext.Current.GetOwinContext());
For<DbContext>().HybridHttpOrThreadLocalScoped().Use(() => new Context());
Scan(x => {
x.AssemblyContainingType(typeof(IOrderHandler<>));
x.AddAllTypesOf(typeof(IOrderHandler<>));
x.ConnectImplementationsToTypesClosing(typeof(OrderHandler<>)); //.OnAddedPluginTypes(y => y.HybridHttpOrThreadLocalScoped());
x.WithDefaultConventions();
});
Scan(x => {
x.AssemblyContainingType(typeof(IQueryHandler<,>));
x.AddAllTypesOf(typeof(IQueryHandler<,>));
x.ConnectImplementationsToTypesClosing(typeof(QueryHandler<,>)); //.OnAddedPluginTypes(y => y.HybridHttpOrThreadLocalScoped());
x.WithDefaultConventions();
});
I get 2 StructureMap building errors:
Result Message:
Test method AuditTests.Audit_Ioc_Valid threw exception:
StructureMap.StructureMapConfigurationException: StructureMap Failures: 2 Build/Configuration Failures and 0 Validation Errors
Profile 'DEFAULT'
Build Error on Instance 'AutoMapper.ConfigurationStore'
for PluginType AutoMapper.ConfigurationStore
- and Instance 'Lambda: IContext.GetInstance()' for PluginType AutoMapper.IConfigurationProvider
- and Instance 'Lambda: IContext.GetInstance()' for PluginType AutoMapper.IConfiguration
No default Instance is registered and cannot be automatically determined for type 'AutoMapper.ITypeMapFactory'
There is no configuration specified for AutoMapper.ITypeMapFactory
Build Error on Instance 'Lambda: HttpContext.Current.GetOwinContext()'
for PluginType Microsoft.Owin.IOwinContext
- and Instance 'Handlers.SignInUserHandler for PluginType Plug.IOrderHandler1[Plug.Messages.SignInUserOrder]
Plug.OrderHandler1[Plug.Messages.SignInUserOrder]
StructureMap.Building.StructureMapBuildException: Failure while building 'Lambda: HttpContext.Current.GetOwinContext()', check the inner exception for details
1.) Lambda: HttpContext.Current.GetOwinContext()
2.) Instance of Microsoft.Owin.IOwinContext
---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.HttpContextExtensions.GetOwinEnvironment(HttpContext context)
at System.Web.HttpContextExtensions.GetOwinContext(HttpContext context)
at lambda_method(Closure , IBuildSession , IContext )
--- End of inner exception stack trace ---
at lambda_method(Closure , IBuildSession , IContext )
at StructureMap.Building.BuildPlan.Build(IBuildSession session, IContext context) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Building\BuildPlan.cs:line 151
at StructureMap.BuildSession.BuildNewInSession(Type pluginType, Instance instance) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\BuildSession.cs:line 108
at StructureMap.Pipeline.NulloTransientCache.Get(Type pluginType, Instance instance, IBuildSession session) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Pipeline\NulloTransientCache.cs:line 28
at StructureMap.BuildSession.ResolveFromLifecycle(Type pluginType, Instance instance) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\BuildSession.cs:line 102
at StructureMap.SessionCache.GetObject(Type pluginType, Instance instance, ILifecycle lifecycle) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\SessionCache.cs:line 88
at StructureMap.BuildSession.FindObject(Type pluginType, Instance instance) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\BuildSession.cs:line 198
at StructureMap.Diagnostics.PipelineGraphValidator.tryBuildInstance(Type pluginType, Instance instance, IPipelineGraph pipeline, ProfileReport report) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Diagnostics\PipelineGraphValidator.cs:line 82
Result StackTrace:
at StructureMap.Diagnostics.PipelineGraphValidator.AssertIsValid() in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Diagnostics\PipelineGraphValidator.cs:line 40
at StructureMap.Diagnostics.PipelineGraphValidator.AssertNoErrors(IPipelineGraph graph) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Diagnostics\PipelineGraphValidator.cs:line 21
at StructureMap.Container.AssertConfigurationIsValid() in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Container.cs:line 485
Any idea how to solve these 2 problems?
Thank You,
Miguel
Related
This is how I am parsing my JSON, It's working but I want to know how would I create an instance of List<Result> to access the data inside it in my widgets. Help, please!
class Test {
Test({
required this.results,
});
List<Result> results;
factory Test.fromJson(Map<String, dynamic> json) => Test(
results:
(json["results"] as List).map((e) => Result.fromJson(e)).toList(),
);
}
Test testFromJson(String str) => Test.fromJson(json.decode(str));
Secondly, when I use this code in the section below instead of the last line of code in the above section, I get the following type error, please tell me what exactly this error means.
_TypeError (type '(dynamic) => Test' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform')
List<Test> modelFromJson(String str) =>
List<Test>.from(json.decode(str).map((x) => Test.fromJson(x)));
Solution
factory Test.fromJson(Map<String, dynamic> json) => Test(
results: (json["results"] as List).map((e) => Result.fromJson(e as Map<String, dynamic>)).toList(),
);
The best solution -
https://docs.flutter.dev/development/data-and-backend/json
I have a mapping between two classes:
CreateMap<A, B>()
.ForMember(b => b.Foo, cfg => cfg.MapFrom(a => a.Aoo.Foo))
.ReverseMap()
.IgnoreAllPropertiesWithAnInaccessibleSetter()
.IgnoreAllSourcePropertiesWithAnInaccessibleSetter()
.ForMember(a => a.Aoo, opts => opts.Ignore());
I would expect, from the last Ignore() alone, that when mapping a B to an A, Automapper would not try to assign a value to A. However, I do such a thing here:
var a = _mapper.Map<A>(b);
And I get the following exception:
System.NullReferenceException : typeMapDestination.Aoo cannot be null because it's used by ForPath.
Why is it trying to assign a value here? I even looked at the source code and this exception only gets thrown when the setter for that property is null!
I have the following automapper code:
CreateMap<JeffreysOnline.Data.BoothMaster, JeffreysOnline.Entities.BoothMaster>()
.ForMember(s => s.RentClass, t => t.MapFrom(m => m.RentClass));
The BoothMaster class contains a class named RentClass. When the mapping occurs I'd like a new instance of RentClass assigned to BoothMaster when RentClass is NULL, instead of a NULL value assigned, as is occurring now when RentClass is NULL. Can this be done?
I haven't tested the code but you should be able to do something like this:
CreateMap<JeffreysOnline.Data.BoothMaster, JeffreysOnline.Entities.BoothMaster>().BeforeMap((source, dest) =>
{
dest.RentClass = (source.RentClass == null) ? new RentClass(): source.RentClass;
});
Is this possible to show a user defined message in package manager console while running a Seed method or throwing any exceptions?
When i am getting below error message from package manager console when throwing exception while running Seed method from Packager manager console my running Seed method has been stopped and not able to process for other seed methods! so I used Try-Catch block to skip those exception and continue other seed methods.
Object reference not set to an instance of an object.
My Seed Methods Seems like this:
context.Subjects.AddOrUpdate(MyRepository.SeedSubject.Subject());
BookTypes
context.BookTypes.AddOrUpdate(b => b.Type,
new BookType { Type = "Audio" },
new BookType { Type = "Book" },
new BookType { Type = "Video" }
);
Books
context.Books.AddOrUpdate(FCA.Repository.SeedBook.Books());
try
{
context.BookSubjects.AddOrUpdate(b => b.BookSubjectID,
new BookSubject { SubjectID = context.Subjects.SingleOrDefault(s => s.Name == "Graduation").SubjectID, BookID = context.Books.SingleOrDefault(b => b.Title == "Graduation Event").BookID },
new BookSubject { SubjectID = context.Subjects.SingleOrDefault(s => s.Name == "Online Courses").SubjectID, BookID = context.Books.SingleOrDefault(b => b.Title == "3rd Grade Online Complete Set").BookID },
new BookSubject { SubjectID = context.Subjects.SingleOrDefault(s => s.Name == "8th Grade").SubjectID, BookID = context.Books.SingleOrDefault(b => b.Title == "Access 2000 Set Lifepac").BookID });
}
catch (Exception ex)
{
//How to display this message in Package Manager Console while running Seed method?
}
How can i show user defined messages in package manager console Or Is this possible to run Seed method with Break-Point?
I have a question with regards to automapping entity framework objects which have been "deep loaded". I have a Project object which has a member called Tasks which is a collection. And each task has a member called Works which is a collection. When the Project is deep loaded, those Tasks and their Works member are all populated. It looks like this:
-- Project
-- Task 1
-- Work 1
-- Work 2
-- Task 2
-- Work 3
I have figured out how to map 1 level deep using a resolver like this:
CreateMap<DataAccess.Task, Entities.Task>()
.ForMember(obj => obj.Description, obj => obj.MapFrom(src => src.Description))
.ForMember(obj => obj.Estimate, obj => obj.MapFrom(src => src.Estimate))
.ForMember(obj => obj.Id, obj => obj.MapFrom(src => src.ID))
.ForMember(obj => obj.ProjectId, obj => obj.MapFrom(src => src.Project))
.ForMember(obj => obj.TaskName, obj => obj.MapFrom(src => src.TaskName))
.ForMember(obj => obj.Visible, obj => obj.MapFrom(src => src.Visible))
.ForMember(obj => obj.WorkItems, obj => obj.ResolveUsing<WorkItemsResolver>().FromMember(src => src.Works));
public class WorkItemsResolver : ValueResolver<EntityCollection<DataAccess.Work>, ICollection<Entities.Work>>
{
#region Overrides of ValueResolver<List<Task>,List<Task>>
protected override ICollection<Entities.Work> ResolveCore(EntityCollection<DataAccess.Work> source)
{
Mapper.EntitiesMapper entitiesMapper = new EntitiesMapper();
return source.Select(wk => entitiesMapper.Map<Entities.Work>(wk)).ToList();
}
#endregion
}
However, I cannot figure out how to go 2 levels deep i.e. to be able to map a top level object (Project) and have it's child lists (and their child lists) also get mapped to their concommitant business objects.
Does anyone know if this is possible with Automapper?
Thanks
You should have a corresponding DataAccess object for each Entity object. You already have a Task mapping, now you need one for Work. Also, don't use separate ValueResolvers. You can do anything you need using the lambda overloads in ForMember.
CreateMap<DataAccess.Task, Entities.Task>()
// when names match on both sides, there is no need to call ForMember
//.ForMember(obj => obj.Description, obj => obj.MapFrom(src => src.Description))
//.ForMember(obj => obj.Estimate, obj => obj.MapFrom(src => src.Estimate))
//.ForMember(obj => obj.Id, obj => obj.MapFrom(src => src.ID))
.ForMember(obj => obj.ProjectId, obj => obj.MapFrom(src => src.Project))
//.ForMember(obj => obj.TaskName, obj => obj.MapFrom(src => src.TaskName))
//.ForMember(obj => obj.Visible, obj => obj.MapFrom(src => src.Visible))
.ForMember(obj => obj.WorkItems, obj => obj.ResolveUsing(src =>
Mapper.Map<IEnumerable<DataAccess.Work>>(src.Works)))
;
CreateMap<DataAccess.Work, Entities.Work>()
// only call ForMember on properties that don't map automatically
;
Since you created a map for your 2'nd level of depth in the object hierarchy, you can just call Mapper.Map in the ResolveUsing lambda overload.