I have started to use the latest MVVM Light toolkit v4 (NuGet preview v4.1.21, DLL v: 4.0.21.25725), which implements the SimpleIOC pattern.
In my ViewModelLocator.cs, I have the following to handle both design and runtime repositories:
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IWebRepository, DesignWebRepository>();
}
else
{
SimpleIoc.Default.Register<IWebRepository, WebRepository>();
}
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
But this gives me the following Exception in the designer (so no compile errors, nor runtime errors, but I loose my Blendability) for the View:
Class Repository.IWebRepository is already registered
(at the first .Register() call)
IWebRepository:
public interface IWebRepository
{
string Test(string data);
}
DesignWebRepository:
public class DesignWebRepository : IWebRepository
{
public string Test(string data)
{
return "design result: " + data;
}
}
WebRepository:
public class WebRepository : IWebRepository
{
public string Test(string data)
{
return "result: " + data;
}
}
MainViewModel:
public class MainViewModel : ViewModelBase
{
IWebRepository webRepository;
public MainViewModel(IWebRepository webRepository)
{
this.webRepository = webRepository;
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
// Code runs "for real"
}
}
}
What am I missing here?
if (ViewModelBase.IsInDesignModeStatic)
{
if (!SimpleIoc.Default.IsRegistered<IRepository>())
{
SimpleIoc.Default.Register<IRepository, DesignWebRepository>();
}
}
else
{
SimpleIoc.Default.Register<IRepository, WebRepository>();
}
Notice the check for if the repository is already registered to prevent double registration. Hope this fixes your problem
Related
I have a simple demo application with ReactiveUI:
//in the viewmodel
class MainViewModel : ReactiveObject
{
public ReactiveUI.ReactiveCommand<Unit, Unit> MyReactiveCommand { get; }
public MainViewModel()
{
MyReactiveCommand = ReactiveCommand.Create(() => { MessageBox.Show("Hello"); }, outputScheduler: RxApp.MainThreadScheduler);
}
}
In the view XAML
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<WrapPanel HorizontalAlignment = "Left">
<Button Content="button" Command="{Binding MyReactiveCommand}"/>
</WrapPanel>
</Grid>
When you press the button there should be a Message Box but instead I get the following error:
System.InvalidOperationException: 'The calling thread cannot access
this object because a different thread owns it.'
I have tried returning a value and then subscribing like Glenn suggested but that had the same problem. At least with this code the Message Box opens before it crashes ;)
public class MainViewModel : ReactiveObject
{
public ReactiveCommand<Unit, Unit> MyReactiveCommand { get; }
public MainViewModel()
{
MyReactiveCommand = ReactiveCommand.CreateFromObservable(DoSometing);
MyReactiveCommand.Subscribe(x => { MessageBox.Show("Hello"); });
}
public IObservable<Unit> DoSometing()
{
return Observable.Start(() => { });
}
}
So a couple things to be aware of. ReactiveCommand.CreateFromObservable has a parameter called outputScheduler and this will be where the Subscribe's output will go to. You can pass RxApp.MainThreadScheduler here.
public class MainViewModel : ReactiveObject
{
public ReactiveCommand<Unit, Unit> MyReactiveCommand { get; }
public MainViewModel()
{
MyReactiveCommand = ReactiveCommand.CreateFromObservable(DoSometing, outputScheduler: RxApp.MainThreadScheduler);
MyReactiveCommand.Subscribe(x => { MessageBox.Show("Hello"); });
}
public IObservable<Unit> DoSometing()
{
return Observable.Start(() => { });
}
}
Note also make sure you have installed the NuGet package ReactiveUI.WPF
In Spring, is there a way I can access the properties of the unitofwork across the DAO's?
Let's assume I have a service layer:
public Class A {
public doSave (){
impl.setUnitOfWork(details);
daoA.saveA(dto.getEntityADetails())
daoB.saveB(dto.getEntityBDetails());
}
}
public class Impl extends TopLinkDaoSupport {
public void setUnitOfWork (TxnDetailsDTO details) {
getSection().getTopLinkTemplate().execute (new UnitOfWorkCallback() {
protected object doInUnitOfWork (UnitofWork uow) {
uow.setProperty ('prop1', details);
return null;
}
});
}
}
public Class DAOA {
public saveA (DTO dto) {
getSection().getTopLinkTemplate().execute (new UnitOfWorkCallback() {
protected object doInUnitOfWork (UnitofWork uow) {
if (uow.getProperty('prop1'))
uow.registerObject(dto);
return null;
}
});
}
}
public Class DAOB {
public saveB (DTO dto) {
getSection().getTopLinkTemplate().execute (new UnitOfWorkCallback() {
protected object doInUnitOfWork (UnitofWork uow) {
if (uow.getProperty('prop1'))
uow.registerObject(dto);
return null;
}
});
}
}
Server is Tomcat.
I have a similar implementation done with WebSphere & that works, but with Tomcat I am not able to access it.
I was reading a post at VS 2008, ASP.NET: Generate Local Resources.
Mehdi Golchin showed us a beautiful job of StateManagedCollection.
However I was wondered about using multiple classes of IStateManager in one StateManagedCollection.
As you can see below:
public class MenuItemCollection : StateManagedCollection
{
public MenuItem this[int index]
{
get { return (MenuItem)((IList)this)[index]; }
}
public int Add(MenuItem item)
{
return ((IList)this).Add(item);
}
public void Remove(MenuItem item)
{
((IList)this).Remove(item);
}
// Write Insert and RemoveAt methods
protected override void SetDirtyObject(object o)
{
((MenuItem)o).SetDirty();
}
}
This MenuItemCollection class can have only one child class("MenuItem").
If I want to use another class as well as MenuItem class, for example MenuItem2 class, how do I have to write the codes?
Anyone can help me?
Thanks in advance.
Write a generic version - for example,
public class GenericStateManagedCollection<T> : StateManagedCollection
where T: IStateManager, new()
{
public T this[int index]
{
get { return (T)((IList)this)[index]; }
}
public int Add(T item)
{
return ((IList)this).Add(item);
}
public void Remove(T item)
{
((IList)this).Remove(item);
}
// Write Insert and RemoveAt methods
protected override void SetDirtyObject(object o)
{
((T)o).SetDirty();
}
protected override object CreateKnownType(int index)
{
return Activator.CreateInstance<T>();
}
protected override Type[] GetKnownTypes()
{
return new Type[] { typeof(T) };
}
}
And use it as
public class MenuItemCollection : GenericStateManagedCollection<MenuItem> { }
public class XyzItemCollection : GenericStateManagedCollection<XyzItem> { }
EDIT:
I have most probably mis-understood your question! Assuming now that you want to put two different type of objects into the StateManagedCollection. From usage perspective, it doesn't make sense to have objects of completely unrelated types into the collection - you need to have some base class. For example, consider DataControlFieldCollection which holds instances of (abstract) type 'DataControField. BoundField, ButtonField etc inherits fromDataControField`.
So you need to go via similar route - for example,
public class MenuItemBase : IStateManager
{
// Use implementation from link you quoted (Mehdi Golchin's answer)
...
}
public class MenuItem : MenuItemBase
{
...
}
public class MenuItem2 : MenuItemBase
{
...
}
public class MenuItemCollection : StateManagedCollection
{
public MenuItemBase this[int index]
{
get { return (MenuItemBase)((IList)this)[index]; }
}
public int Add(MenuItemBaseitem)
{
return ((IList)this).Add(item);
}
public void Remove(MenuItemBaseitem)
{
((IList)this).Remove(item);
}
// Write Insert and RemoveAt methods
protected override void SetDirtyObject(object o)
{
((MenuItemBase)o).SetDirty();
}
// important to override CreateKnownType and GetKnownTypes
private static readonly Type[] _knownTypes = new Type[] {typeof(MenuItem), typeof(MenuItem2) }
protected override Type[] GetKnownTypes()
{
return _knownTypes;
}
protected override object CreateKnownType(int index)
{
switch (index)
{
case 0:
return new MenuItem();
case 1:
return new MenuItem2();
default:
throw new Exception("Invalid Index");
}
}
}
Note: Untested code
I'm trying to setup the following:
/WebApplication
web.config
tokenlogin.aspx
/Services
web.config
AccessTokenService.svc
I put my WCF Service + configuration in the /WebApplication/Services folder.
This still workes as expected.
Now my AccessTokenService, which resides in an other assembly, expects an interface in its constructor called IAccessTokenRepository (see all code samples below).
Because normally WCF only allows for parameter-less constructors, I extended WCF using a custom IInstanceProvider, IServiceBehavior and BehaviorExtensionElement so Unity could resolve this for me.
As I did with the WCF configuration, I also put the Unity configuration inside the web.config file which resides in the Services folder. This way I don't pollute my web.config in my web app root. But that doesn't seem to work. I'm unable to read the unity configuration section from the web.config in the services folder. The GetSection part of the follwing code returns null:
public class UnityBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(UnityServiceBehaviour); }
}
protected override object CreateBehavior()
{
UnityContainer unityContainer = new UnityContainer();
UnityConfigurationSection section = LoadUnitySection() as UnityConfigurationSection;
section.Containers.Default.Configure(unityContainer);
return new UnityServiceBehaviour(unityContainer);
}
private object LoadUnitySection()
{
if (System.Web.Hosting.HostingEnvironment.IsHosted)
return WebConfigurationManager.GetSection("unity");
return ConfigurationManager.GetSection("unity");
}
}
Now if I move the unity configuration to the web.config int the root of the WebApplication everything works fine. And I have no idea why.
The rest of the code:
[ServiceContract(Namespace = "http://services.xxx.com/AccessTokenService/1.0")]
public interface IAccessTokenService
{
[OperationContract]
Guid RequestAccessToken(AccessTokenRequest accessTokenRequest);
}
public class AccessTokenService : IAccessTokenService
{
private readonly IAccessTokenRepository accessTokenRepository;
public AccessTokenService(IAccessTokenRepository accessTokenRepository)
{
if (accessTokenRepository == null)
throw new ArgumentNullException("accessTokenRepository");
this.accessTokenRepository = accessTokenRepository;
}
public Guid RequestAccessToken(AccessTokenRequest accessTokenRequest)
{
return accessTokenRepository.Store(accessTokenRequest);
}
}
public class UnityInstanceProvider : IInstanceProvider
{
private readonly Type serviceType;
private readonly UnityContainer unityContainer;
public UnityInstanceProvider(Type serviceType, UnityContainer unityContainer)
{
this.serviceType = serviceType;
this.unityContainer = unityContainer;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return unityContainer.Resolve(serviceType);
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
if (instance == null)
return;
if (instance is IDisposable)
((IDisposable)instance).Dispose();
}
#endregion
}
public class UnityServiceBehaviour : IServiceBehavior
{
private readonly UnityContainer unityContainer;
public UnityServiceBehaviour(UnityContainer unityContainer)
{
this.unityContainer = unityContainer;
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (var channel in serviceHostBase.ChannelDispatchers.OfType())
{
if (channel == null)
continue;
foreach (var endPointDispatcher in channel.Endpoints)
{
endPointDispatcher.DispatchRuntime.InstanceProvider =
new UnityInstanceProvider(serviceDescription.ServiceType, unityContainer);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
CS0234: The type or namespace name 'ShoppingCart' does not exist in the namespace 'MyWebsite.Commerce' (are you missing an assembly reference?)
public class ProfileCommon : System.Web.Profile.ProfileBase {
public virtual MyWebsite.Commerce.ShoppingCart Cart {
get {
return ((MyWebsite.Commerce.ShoppingCart)(this.GetPropertyValue("Cart")));
}
set {
this.SetPropertyValue("Cart", value);
}
}
public virtual string Country {
get {
return ((string)(this.GetPropertyValue("Country")));
}
set {
this.SetPropertyValue("Country", value);
}
}
public virtual string Gender {
get {
return ((string)(this.GetPropertyValue("Gender")));
}
set {
this.SetPropertyValue("Gender", value);
}
}
public virtual int Age {
get {
return ((int)(this.GetPropertyValue("Age")));
}
set {
this.SetPropertyValue("Age", value);
}
}
public virtual ProfileCommon GetProfile(string username) {
return ((ProfileCommon)(ProfileBase.Create(username)));
}
}
when i run this page the an error occured and when i clicked the error line it goes to above code please anyone help me ASAP please.......
Check your project references - most likely the one that points to the assembly that contains MyWebsite.Commerce.ShoppingCart is missing. Is this a project reference? Perhaps you simply haven't built the solution yet.