I have an entity like so:
public class Land
{
public virtual IDictionary<string, int> Damages { get; set; }
// and other properties
}
Every time I try to use automapping with the following code:
var sessionFactory = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory)
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Land>))
.BuildSessionFactory();
I get the following error:
{"The type or method has 2 generic parameter(s), but 1 generic argument(s) were
provided. A generic argument must be provided for each generic parameter."}
Can someone tell me what I'm doing wrong? Also, this is just a simple example. I have much more dictionaries than just this one.
It is impossible with NHibernate.
Found some traces that this isn't possible. Some traces, that it's recently implemented.
Still investigating. :)
This looks quite promising (didn't test yet).
So, in your case it should look like=>
public class LandMap : ClassMap<Land>
{
public LandMap()
{
(...)
HasMany(x => x.Damages)
.WithTableName("Damages")
.KeyColumnNames.Add("LandId")
.Cascade.All()
.AsMap<string>(
index => index.WithColumn("DamageType").WithType<string>(),
element => element.WithColumn("Amount").WithType<int>()
);
}
}
Keep in mind - it should. I didn't test it.
A possible workaround that should in theory work with automapping:
public class DamagesDictionary : Dictionary<string, int>
{
}
Land.cs
public class Land
{
public virtual DamagesDictionary Damages { get; set; }
// and other properties
}
or a more generic approach...
public class StringKeyedDictionary<T> : Dictionary<string, T>
{
}
Land.cs
public class Land
{
public virtual StringKeyedDictionary<int> Damages { get; set; }
// and other properties
}
Related
I am writting a DDD application and I am trying to use LazyLoading option.
The problem I am facing is that I can run my application OK if I don't use LazyLoading, but once I try to use UseLazyLoadingProxies(), when I get an entity I get the title exception. It seems that is thrown at Castle.DynamicProxies as I can see in the stacktrace
This is my entity:
public class Technology //: Entity
{
// fields
private readonly IList<SubTechnology> subTechnologies = new List<SubTechnology>();
// properties
public long Id { get; private set; }
public virtual TechnologyName Name { get; private set; }
public virtual IReadOnlyList<SubTechnology> SubTechnologies => subTechnologies.ToList().AsReadOnly();
public Technology() { }
public Technology(TechnologyName technologyName) : this()
{
Name = technologyName;
}
//public void AddSubtechnology(SubTechnology subTech)
//{
//}
and this is how I am calling my code:
public sealed class QuestionController
{
private readonly InterviewsDbContext context;
public QuestionController(InterviewsDbContext context)
{
this.context = context;
}
public string GetTechnology(long technologyId)
{
var tech = context.Technology.Single(t => t.Id == technologyId);
return tech?.Name.Value;
}
}
To me is indicating that I don't have my CTOR implemented, but I have tried public, protected, internal and I can't seem to make it work.
The only thing I can tell is that the Domain model do not live in the same assembly that my Context lives... not sure if has to do with the issue..
Any ideas? thx
Well I think I am really stupid, I just transformed my code into something really dumb (anemic model) and the problem went away.
What I figured out was that the backing field being a IList<T> and the Property of type IReadOnlyList<T> and the proxy couln't create the type.
The exception error was not much helpful in this case but changing IList<T> to List<T> fixed my issue.
To share data (complexe data ) between pages in my windows phone 8 application I want to implement a singleton, but I want it to be generic, is it possible? I suppose that it creates a new instance for each type isn't it?
public sealed class NavigationContextService<T>
{
private static readonly NavigationContextService<T> instance = new NavigationContextService<T>();
private NavigationContextService()
{
}
public static NavigationContextService<T> Instance
{
get
{
return instance;
}
}
public List<T> ShareList { get; set; }
public T ShareData { get; set; }
}
It is creating a new instance for every type, because it is generic - you want it to be like this (if you start with generics, take a look at some tutorials, blogs or MSDN - you will easily find many in the internet).
It is still a singleton. When you use
NavigationContextService<string>.Instance.ShareList.Add("Text");
then you have one Instance for type string. Generics helps a lot when you want to create same methods/classes that differ in type.
On the other hand if you want to create Singleton that will hold different types then you can for example modify your class to be non Generic like this:
public sealed class NavigationContextServiceNonGeneric
{
private static readonly NavigationContextServiceNonGeneric instance = new NavigationContextServiceNonGeneric();
private NavigationContextServiceNonGeneric() { ShareList = new List<object>(); }
public static NavigationContextServiceNonGeneric Instance
{ get { return instance; } }
public List<object> ShareList { get; set; }
public object ShareData { get; set; }
}
As you can see in the code above I haven't defined the 'exact' type of shared data - it is object type. Then you can easily hold most of data with it:
NavigationContextServiceNonGeneric.Instance.ShareList.Add("Text");
NavigationContextServiceNonGeneric.Instance.ShareList.Add(3);
NavigationContextServiceNonGeneric.Instance.ShareList.Add(3.0f);
It is singleton, which can hold different types of shared data. BUT it has also disavantages - the main is that you have to remember what type of data you hold and in what order. In my opinion Generic version is better because of that fact.
Everything depends on the purpose of your code. There may be easier and better ways that those two approaches.
As for the Page Navigation, you can for example try to use a method from this article - you extend Navigation service to pass the object:
public static class Extensions
{
private static object Data;
public static void Navigate(this NavigationService navigationService, Uri source, object data)
{
Data = data;
navigationService.Navigate(source);
}
public static object GetNavigationData(this NavigationService service) { return Data; }
}
Then you use it:
NavigationService.Navigate(yourUri, DataToPass);
After Navigation you can get your data:
string myTextData = NavigationService.GetNavigationData() as string;
This method has to disadvantages: it is not type-safe and your data won't be preserved in Tombstone mode.
As for the second disadvantage you can easily use PhoneApplicationService.State Property for the purpose of Page Navigation - it is a dictionary (which is preserved while tombstoning):
PhoneApplicationService.Current.State.Add("data", yourData);
Then when you want to get your data:
yourDataType yourData = PhoneApplicationService.Current.State["data"] as yourDataType;
There are also more ways in which you can pass the data.
What is the recommended method of passing a parameter from one viewmodel to another, modifying it then returning it to the original viewmodel?
Much has been written about passing values in to views ie ShowViewModel(new{ paramX=valueY} ), however I am unable to find any working examples of having the displayed 'submodel' return a value back to the parent when it is closed/dismissed in some method.
The only sample I've found which seems to cover this is http://www.gregshackles.com/2012/11/returning-results-from-view-models-in-mvvmcross/ however the code doesn't seem to work on the new current v3 mvx, failing at runtime with error resolving the viewmodel type, presumably because reflection in mvx wasn't able to identify/register the type due to subtyping or generics.
After discussing with the author of the link from my question, the code does work with one minor tweak and a correction to the name of my View class to conform to the mvvmcross convention.
My view was incorrectly named SomethingViewController rather than SomethingView.
The alteration to Greg's code to work on the current MVX v3 codebase is to change his sample from:
public abstract class SubViewModelBase<TResult> : ViewModelBase
{
protected string MessageId { get; private set; }
protected SubViewModelBase(string messageId)
{
MessageId = messageId;
}
....
}
to:
public abstract class SubViewModelBase<TResult> : ViewModelBase
{
protected string MessageId { get; private set; }
public virtual void Init(string messageId){
this.MessageId = messageId;
}
}
and of course in your submodels use
public abstract class MySomeModel : SubViewModelBase<YourReturnType>
{
public override void Init(string messageId, other.. parameters..){
base.Init(messageId);
.. your other parameters init here..
}
}
Maybe abstract typed factories are not an easy point to start with Windsor (2.5.3 if it matters) but I've got to do it anyway.
I'm trying to build a factory giving back processors depending on message type. So far i've scavenged from different places following code:
public class Complicato
{
public static void Do(string[] args)
{
IKernel kernel = new DefaultKernel();
IWindsorContainer container = new WindsorContainer();
kernel.AddFacility<TypedFactoryFacility>();
container.Install();
container.Register(
Component.For<HandlerSelector, ITypedFactoryComponentSelector>(),
AllTypes.FromThisAssembly().BasedOn(typeof(ITrier<>))
.WithService.Base().Configure(conf => conf.LifeStyle.Is(LifestyleType.Transient)),
Component.For<Factor>(),
Component.For<ITryFactory>().AsFactory(c => c.SelectedWith<HandlerSelector>()).LifeStyle.Singleton);
var factor = container.Resolve<Factor>();
var factory = container.Resolve<ITryFactory>();
}
}
public class HandlerSelector : DefaultTypedFactoryComponentSelector
{
protected override Type GetComponentType(MethodInfo method, object[] arguments)
{
return typeof(ITrier<>).MakeGenericType(arguments[0].GetType());
}
}
public class Factor
{
private ITryFactory factory;
public void Try(IWhat onto)
{
factory.GetTrier(onto).Try(onto);
}
}
public interface ITryFactory
{
ITrier<IWhat> GetTrier(IWhat onto);
void Release(object elem);
}
public interface IWhat { }
public interface ITrier<in TWhat> where TWhat : IWhat
{
void Try(TWhat input);
}
public class TrierYes : ITrier<WhatYes>
{
public void Try(WhatYes input) { Console.WriteLine("Yes? " + input.Aye()); }
}
public class TrierNo : ITrier<WhatNot>
{
public void Try(WhatNot input) { Console.WriteLine("No? " + input.Naa()); }
}
public class WhatYes : IWhat
{
public bool Aye() { return true; }
}
public class WhatNot : IWhat
{
public bool Naa() { return false; }
}
Main problem here is that id doesn't work. First I get Factor with factory of null and then as a consequence trying to resolve factory explicitely gives me ComponentActivator: could not proxy Factories.Complex.ITryFactory with inner message of The interceptor Castle.TypedFactory.Interceptor could not be resolved and "Keys (components with specific keys) - Castle.TypedFactory.Interceptor which was not registered" in container. I don't even know if the Handler selector works, it's not in question so far.
If I make ITrier not generic - it suddenly starts working but it's definitely not what I'm trying to achieve.
So do I make some silly beginners mistake in Windsor configuration or misunderstand the idea of typed factory?
For completeness sake, here's the exception message:
Castle.MicroKernel.ComponentActivator.ComponentActivatorException was unhandled
Message=ComponentActivator: could not proxy Factories.Complex.ITryFactory
Source=Castle.Windsor
StackTrace:
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, Object[] arguments, Type[] signature) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\ComponentActivator\DefaultComponentActivator.cs:line 166
InnerException: Castle.MicroKernel.Resolvers.DependencyResolverException
Message=The interceptor Castle.TypedFactory.Interceptor could not be resolved
Source=Castle.Windsor
StackTrace:
at Castle.Core.InterceptorReference.Castle.MicroKernel.IReference<Castle.DynamicProxy.IInterceptor>.Resolve(IKernel kernel, CreationContext context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\Core\InterceptorReference.cs:line 142
And the winner is
container.AddFacility<TypedFactoryFacility>(); // good code
instead of
kernel.AddFacility<TypedFactoryFacility>(); // bad code
Now I only have the issues of not injected factory and improper HandlerSelector.
NullReference was solved by introducing explicit initializing constructor to the Factor. I don't know why I thought it works without.
Final version of the handler interface is following:
public interface ITrier<out TWhat> where TWhat: IWhat
{
void Try(IWhat input);
}
To permit covariance. Not über-elegant as requires unnecessary cast and handlers loosen their typedness. But this is cruel reality. You're either co or contra-variant.
I'm currently registering a bunch of stuff at one point in my initialisation sequence
Container.Register(AllTypes.FromAssemblyContaining<MyAssembly>()
.BasedOn(typeof(IRepository<>))
.WithService.Self().Configure(c => c.LifeStyle.Transient));
I'm using WithService.Self so that it doesn't automatically pick up AllInterfaces, so that the interface that I will want to add later on as a type forward has not already been added.
I'd like then (later on) to be able to add a type forward to one of the already registered components, and Intellisense on the ForwardedTypes property suggested using .Forward(typof()) e.g.
Container.Register(Component.For<IOtherInterface>()
.Forward(typeof(IOtherInterface))
.ImplementedBy<AlreadyRegisteredType>().LifeStyle.Transient);
Is this possible?
EDIT:
I've been trying to get the stuff that Krzysztof has suggested working so I've generated a test project (below). I've tried various combinations to get the ConfigureFor to forward IMyInterface to MySecondType, but just can't get it to work, when done as a second step after initial registration of my component types. I'm probably being dim, but I'm just not getting how the ConfigureFor command works, and the documentation is a little sketchy (non-existant) on the subject.
namespace TestProject1
{
public class MyType : IMyInterface
{
public virtual string MyProperty { get; set; }
}
public class MySecondType : IMyInterface
{
public virtual string MySecondProperty { get; set; }
}
public interface IMyInterface
{
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
//New Container
var container = new WindsorContainer();
//Register Types
container.Register(
AllTypes.FromAssemblyContaining<MyType>().BasedOn<IMyInterface>().WithService.Self().Configure(
c => c.LifeStyle.Transient));
//Other stuff happens here...
//Now Register our interface as a forward
container.Register(AllTypes.FromAssemblyContaining<IMyInterface>()
.BasedOn<IMyInterface>()
.WithService.Base()
.ConfigureFor<IMyInterface>(r => r.Forward<MySecondType>()).Configure(c => c.LifeStyle.Transient));
var typeA = new MySecondType();
var typeB = container.Resolve<IMyInterface>();
Assert.IsInstanceOfType(typeB.GetType(), typeA.GetType());
}
}
}
What you described in the comment is registering another component for the AlreadyRegisteredType.
If you want to add a forward to the same component use
ConfigureFor<AlreadyRegisteredType>(c => c.Forward<IOtherInterface>())
full example:
Container.Register(AllTypes.FromThisAssembly()
.BasedOn<IEmptyService>()
.WithService.Base()
.ConfigureFor<EmptyServiceComposite>(r => r.Forward<EmptyServiceComposite>()));
Once you registered some type
Container.Register(Component.For<SomeType>());
you can forward some interface to it in this way:
Container.Register(Component.For<ISomeInterface>()
.UsingFactoryMethod<ISomeInterface>(kernel => kernel.Resolve<SomeType>()));