Very Basic StructureMap? - structuremap

Ok, I wrote this question up earlier today but I decided to delete it because I thought the question wasn't worded very well. I decided to wait until I had more time to compose it at home :).
I am just getting started with IOC/DI. I have done some research on which framework to use and decided to give StructureMap a spin. The following is the first tutorial I used:
http://dimecasts.net/Casts/CastDetails/39 by Derik Whittaker.
Anyways, I got everything working like a dream with EVERYTHING is hosted in the same project.
Here is my sample code:
[PluginFamily("SMTest",IsSingleton=true)]
public interface IVehicle
{
byte TopSpeed {set;get;}
byte MPG { set; get; }
}
[Pluggable("SMTest")]
public class Car : IVehicle
{
private byte mTopSpeed;
private byte mMPG;
#region IVehicle Members
byte IVehicle.TopSpeed
{
get
{
return mTopSpeed;
}
set
{
mTopSpeed = value;
}
}
public interface IConsumer
{
IVehicle Car { get; set; }
}
[Pluggable("SMTest")]
public class Consumer : StructureMapBasic.IConsumer
{
private IVehicle mCar;
public Consumer(IVehicle lcar)
{
Car = lcar;
}
public IVehicle Car { set; get; }
byte IVehicle.MPG
{
get
{
return mMPG;
}
set
{
mMPG = value;
}
}
#endregion
}
So anyways if i create the project above into a command line program and do the following:
var consumer = ObjectFactory.GetInstance<IConsumer>();
It works perfectly. No problems at all. When i create a seperate project in the solution and then change the project above to a DLL. I get the following error:
Test method StructureMapBasic.ConsumerTest.ConsumerConstructorTest
threw exception: StructureMap.StructureMapException: StructureMap
Exception Code: 202 No Default Instance defined for PluginFamily
StructureMapBasic.IConsumer, StructureMapBasic, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null.
At first i thought maybe the StructureMap.Config file didn't get into the new projects bin folder but that wasn't the case. It was there. Everythign compiles just fine this problem happens at runtime. I'm sure the solution is very easy but for the life of me i can't figure out whats going wrong. Any help would be MUCH appreciated.
Thanks,
Ncage

I took me all friggn day to figure this out. At first i thought i was just being an idiot and i was missing something stupid. Well i was not. I thought it was related to different projects but it was not. I created a new console application that consumed my StructureMapped DLL (If just coined a term ;) ). Anyways, after trying to spend all day on this problem i FINALLY found a post that described the problem. its a freakn bug in MSTest (my project i was having problems with was created in MSTest). Xunit here i come. Here is a post that describes the issue from the same guy who created the tutorial video:
http://devlicio.us/blogs/derik_whittaker/archive/2008/07/23/mstest-why-i-hate-you-you-cause-me-too-much-friction.aspx

Related

Glass Mapper loads collections only for interfaces

Using Sitecore 10.2 and Glass Mapper 5.8.180
After upgrade from Sitecore 8.2 and switching to above mentioned version of Glass Mapper our code stopped loading collection references. I am aware that in Glass Mapper now the lazy loading is turned on by default and I want to keep this setting.
Problem is with follows:
Having
[SitecoreType(TemplateId = "{...}", AutoMap = true)]
public interface IStatementContainer
{
IEnumerable<Statement> Statements { get; set; }
}
public class StatementContainer : IStatementContainer
{
public virtual IEnumerable<Statement> Statements { get; set; }
}
The following code
_mvcContext.SitecoreService.GetItem<StatementContainer>(datasource)
does not work properly. The Statements are empty.
For following code
_mvcContext.SitecoreService.GetItem<IStatementContainer>(datasource)
the Statements are being loaded properly.
Could you explain me the difference in behavior?
Our legacy code contains a lot of usages of concrete types rather than interfaces, changing all of them would be difficult.

Jersey: How to inject EJB into sub resource?

I would like to inject a buisiness service bean in a sub resource which is defined in a dedicated class and delivered by a sub resource locator.
Some example code:
A root resource
#RequestScoped
#Path("service")
public class MyResource {
#Context
ResourceContext resourceContext;
// Sub resource locator
#Path("subservice")
public MySubResource locateToSubResource () {
// I don't want to create it myself.
return resourceContext.getResource(MySubResource.class);
}
}
The corresponding sub resource
#RequestScoped
public class MySubResource {
// Note that businessBean itself consists of
// multiple ejbs that also need to be injected so that it can do its job!
#Inject
private BusinessBean businessBean;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String get () {
return businessBean.doStuff();
}
}
Jersey won't CDI let invoke the dependencies... Note that the resources are managed objects. Otherwise it wouldn't even be possible to inject a bean in a root resource (here I'm pushing my other questions' view count to get more opinions ;-))!
I tried everything I can think of but it just won't work...
Currently I'm using the libraries that are shipped with glassfish 4.
And of course, thank you in advance (almost forgot that)!
Okay, I figured it out.
It is really kind of stupid. Sometimes you have to roll back completely.
There must have been something wrong with my initial attempt (typo, left out something...I cannot reproduce it, whatever).
I slightly changed the root resource from above:
#RequestScoped
#Path("service")
public class MyResource {
#Inject MySubResource mySubResource;
// Sub resource locator
#Path("subservice")
public MySubResource locateToSubResource () {
return mySubResource;
}
}
Yes, that's it. I must admit, that's the most intuitive solution one can imagine and if such an approach don't work one must have done something wrong... Dont't ask me what exactly was the cause.
I guess it's as always - sleep deprivation let people turn into morons.
I solved like this.
public SubResource subResource() {
return CDI.current().select(SubResource.class).get();
}

Sporadic "an interface and cannot be constructed. Are you missing a type mapping"

Initial deployment of the site works fine. After about 2-3 hours, the controllers suddenly cannot be instantiated due to a dependency cannot be resolved (or at least that's what the error message tells me).
I have tried various things, but none of which seem to resolve it. Does anyone have any ideas what I can check?
Recently we had a similar situation with one of our Interceptors. All of a sudden it would no longer work. We intercept all calls to interfaces defined in assembly X.Y.Z.dll. But the OS decided to call the file X.Y.Z.DLL after a while. No new deployment happened in the meantime. But all of a sudden the name matching failed. Do you load some assemblies in your configuration by name? Maybe you should check for IgnoreCase in string comparisons.
Another idea: Do you use some kind of cache for your objects? Or a cache based LifetimeManager? If cache items get invalidated after some time you would loose those objects.
i still have no idea what was happening, but i managed to fix it. i was using a third-party bootstrapping library to register my components and mappings. but after rolling my own with MEF, and controlling the registrations myself, the issue went away. i'm guessing it was doing something funky by disposing things when it shouldn't have. thanks for the help.
In case someone encounters this problem using http://bootstrapper.codeplex.com/ with the following declaration:
Bootstrap.Bootstrapper
.With.Unity()
.And.AutoMapper()
.And.ServiceLocator()
.Start();
I replaced that with:
IUnityContainer container = new UnityContainer();
MEFContainer mefContainer = new MEFContainer();
mefContainer.UnityRegistry.ForEach(x => x.Register(container));
container.RegisterInstance<IMappingEngine>(Mapper.Engine);
mefContainer.AutoMapperRegistry.ForEach(x => x.CreateMap(Mapper.Configuration));
where
private class MEFContainer
{
[ImportMany(typeof(IUnityRegistration))]
public List<IUnityRegistration> UnityRegistry { get; set; }
[ImportMany(typeof(IMapCreator))]
public List<IMapCreator> AutoMapperRegistry { get; set; }
public MEFContainer()
{
var catalog = new DirectoryCatalog("bin");
var compositionContainer = new CompositionContainer(catalog);
compositionContainer.ComposeParts(this);
}
}
Note that IUnityRegistration.Register() and IMapCreator.CreateMap() are defined in the third-party code. MEF references System.ComponentModel.Composition
and System.ComponentModel.Composition.Hosting. Will eventually refactor.

Query Orchard CMS from IShapeFactoryEvents

I am trying to insert shapes into my layout from my module once it has been enabled. I figured IShapeFactoryEvents would be perfect for this, but querying the CMS from here gives me a "TransactionScope nested incorrectly exception" if this occurs during a POST. Wondering if anyone had any words of wisdom for me again? See my code snippet below.
public void Created(ShapeCreatedContext context)
{
if (context.ShapeType == "Layout")
{
if (!AdminFilter.IsApplied(_services.WorkContext.HttpContext.Request.RequestContext))
{
var route = RouteTable.Routes.GetRouteData(_services.WorkContext.HttpContext);
object location;
if (route.Values.TryGetValue("location", out location))
{
var region = _services.ContentManager.Query("Region")
.Join<RoutePartRecord>()
.Where(x => x.Slug == (string)location)
.Slice(1).FirstOrDefault();
context.Shape.Header.Add(context.New.CurrentRegion(Title: region.As<RoutePart>().Title), "10");
}
context.Shape.Navigation.Add(context.New.RegionSelector(Regions: _services.ContentManager.Query(VersionOptions.Published, "Region").List()), "11");
}
}
}
Once again, thanks in advance. You guys are awesome.
See the blog post I did on this very topic here: http://chrisbower.com/2011/02/15/orchard-shape-wizardry/
From the blog post:
"One thing I need to note, and this took me an entire day to discover, is that you can't just inject your data service into your IShapeTableProvider implementation. If you do, it'll try to use a transaction out of scope and that will cause you all kinds of problems. After tearing my hair out for hours on end, I finally discovered what the Orchard team is doing inside of the CoreShapes class: The trick to resolve a service dependency within the function itself by using a property that loads the service per-request."
Try using your service like this instead:
private IOrchardServices Services
{
get
{
return _workContextAccessor.GetContext(_httpContextAccessor.Current()).Resolve<IOrchardServices>();
}
}

L2S DataContext out of synch: row not found or changed

Psssst...!
Read on, by all means. But I can tell you here that the problem had nothing to do with the DataContext, but with Dependency Injection. I have left the question up, as it documents one possible issue with the "row not found or changed error" that has nothing to do with real world concurrency conflicts.
It seems the problems have been caused by badly written dependency injection. Or rather, I am beginning to believe, by default lifecycle management by the DI container I used.
The problem was that I used a DataContext as a constructor argument that was supplied by Ninject. It seems that the default behaviour was to cache this DataContext, leading to all manner of unexpected behaviour. I will ask a separate question about this.
Anyway, what follows is my original question, which as you will see, misses the real cause of the issue by a mile...
The Problem
I am getting a number of errors that imply that the DataContext, or rather, the way I am using the DataContext is getting out of synch.
The error occurs on db.SubmitChanges() where db is my DataContext instance. The error is:
Row not found or changed.
The problem only occurs intermitently, for example, adding a row then deleting it. If I stop the dev server and restart, the added row is there and I can delete it no problem.
Ie, it seems that the problem is related to the DataContext losing track of the rows that have been added.
IMPORTANT:
Before anyone votes to close this thread, on the basis of it being a duplicate, I have checked the sql server profiler and there is no "Where 0 = 1" in the SQL.
I have also recreated the dbml file, so am satisfied that the database schema is in synch with the schema represented by the dbml file.
Ie, no cases of mismatched nullable/not nullable columns, etc.
My Diagnosis (for what it is worth):
The problem seems (to me) related to how I am using the DataContext. I am new to MVC, Repositories and Services patterns, so suspect that I have wired things up wrong.
The Setup
Simple eLearning app in its early stages. Pupils need to be able to add and delete courses (Courses table) to their UserCourses.
To do this, I have a service that gets a specific DataContext instance Dependency Injected into its constructor.
Service Class Constructor:
public class SqlPupilBlockService : IPupilBlockService
{
DataContext db;
public SqlPupilBlockService(DataContext db)
{
this.db = db;
CoursesRepository = new SqlRepository<Course>(db);
UserCoursesRepository = new SqlRepository<UserCourse>(db);
}
// Etc, etc
}
The CoursesRepository and UserCoursesRepository are both private properties of the service class that are of type IRepository (just a simple generic repository interface).
SqlRepository Code:
public class SqlRepository<T> : IRepository<T> where T : class
{
DataContext db;
public SqlRepository(DataContext db)
{
this.db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
db.SubmitChanges();
}
#endregion
}
The two methods for adding and deleting UserCourses are:
Service Methods for Adding and Deleting UserCourses:
public void AddUserCourse(int courseId)
{
UserCourse uc = new UserCourse();
uc.IdCourse = courseId;
uc.IdUser = UserId;
uc.DateCreated = DateTime.Now;
uc.DateAmended = DateTime.Now;
uc.Role = "Pupil";
uc.CourseNotes = string.Empty;
uc.ActiveStepIndex = 0;
UserCoursesRepository.Add(uc);
UserCoursesRepository.Save();
}
public void DeleteUserCourse(int courseId)
{
var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single();
UserCoursesRepository.Delete(uc);
UserCoursesRepository.Save();
}
Ajax
I am using Ajax via Ajax.BeginForm
I don't think that is relevant.
ASP.NET MVC 3
I am using mvc3, but don't think that is relevant: the errors are related to model code.
The problem only occurs intermitently,
for example, adding a row then
deleting it. If I stop the dev server
and restart, the added row is there
and I can delete it no problem.
Your code does not show what the link is between the Added Row and the Delete/Update. Your Add() doesn't return an object reference.
I'm thinking you are missing a Refresh (ie reload the object after Insert). Is your IdCourse also the PK in the Table?
Edit:
Further research has revealed that the problem is with the dependency injection.
The problem was related to how Dependency Injection manages the items it creates. Google for 'lifecycle management' in IoC or DI. Essentially, DI cached a DataContext constructor argument that I injected.
For a way to solve this using the Factory Pattern, see this thread:
Ninject caching an injected DataContext? Lifecycle Management?
The accepted answer solved it all.

Resources