How to avoid Custom type name clash generated in WCF Client - wcf

A custom type (e.g. Engine) is defined in two different namespaces on WCF server side, which is exposed to WCF client as Engine, Engine1. How to set up so that the exposed types have the same name, Engine in this case.
Below is my example code:
namespace WcfServiceLibrary1
{
[ServiceContract]
interface ICar
{
[OperationContract]
void RepairMotorCycle(MotorCycle motorCycle);
[OperationContract]
void RepairTwoDoorCar(TwoDoorCar Car);
}
public class Car:ICar
{
public void RepairMotorCycle(MotorCycle motorCycle)
{
throw new NotImplementedException();
}
public void RepairTwoDoorCar(TwoDoorCar Car)
{
throw new NotImplementedException();
}
}
}
namespace WcfServiceLibrary1.MC
{
public class MotorCycle
{
public Engine Engine { get; set; }
}
public class Engine { }
}
namespace WcfServiceLibrary1.C
{
public class TwoDoorCar
{
public Engine Engine { get; set; }
}
public class Engine { }
}
Below is the WCF client for Engine:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="Engine", Namespace="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1.MC")]
[System.SerializableAttribute()]
public partial class Engine : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="Engine", Namespace="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1.C")]
[System.SerializableAttribute()]
public partial class Engine1 : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
}
Please note that both MotoCycle and TwoDoorCar contain a large number of custom type that have the same name but different function. Thus, it is tedious to change the name on client side (e.g. change Engine1 to Engine for all occurences). Also it is tedious to solve it by using class inheritance. It is ok to define two custom types that have the same name, which might need less work.
Any idea would be very much appreciated!
Edit
*Possible Solution*
Put it into separate interface, as below
[ServiceContract]
interface ICar1
{
[OperationContract]
void RepairMotorCycle(MotorCycle motorCycle);
}
[ServiceContract]
interface ICar2
{
[OperationContract]
void RepairTwoDoorCar(TwoDoorCar Car);
}
This will put the same custom type in different namespace on client side.

If your Engines represent an identical concept, you could define one Engine in a dedicated namespace and reference it from WcfServiceLibrary1.MCand WcfServiceLibrary1.C.
Your example however suggests that you should rather gather your vehicles into a single namespace and make use of inheritance.
namespace WcfServiceLibrary.Vehicles
{
public class Engine
{
}
public abstract class Vehicle
{
public Engine { get; set; }
}
public class Car : Vehicle
{
}
pulic class Motorcycle : Vehicle
{
}
}
Moving your Engine to a common namespace could look like this:
namespace WcfServiceLibrary.Common
{
public class Engine
{
}
}
Your "Motorcycle" library
using WcfServiceLibrary.Common
namespace WcfServiceLibrary.MC
{
public class Motorcycle
{
public Engine Engine { get; set; }
}
}
... and your "Car" library
using WcfServiceLibrary.Common
namespace WcfServiceLibrary.C
{
public class Car
{
public Engine Engine { get; set; }
}
}
You won't have to change your Engine property.

First of all, try and share your code libraries between the server and client. This link will tell you how to do it for Silverlight, if you are not using Silverlight then check this SO search link for a variety of posts and answers on the subject.
Secondly, if you cannot share the libraries then editing the generated client class files will work (just delete the definition of Engine1 and fix up any references to it to point to the Engine), although you will lose the changes if you regenerate the proxy.

Related

Cannot create a DbSet for 'Model' because this type is not included in the model for the context

I do a Generic and using DI
so I create a empty class
public class DBRepo
{
}
and my model class to inheriting class DBRepo
public partial class UserAccount : DBRepo
{
public int Id { get; set; }
public string Account { get; set; }
public string Pwd { get; set; }
}
then this is a Interface to do CRUD
public interface IDBAction<TEntity> where TEntity : class,new()
{
void UpdateData(TEntity _entity);
void GetAllData(TEntity _entity);
}
public class DBService<TEntity> : IDBAction<TEntity> where TEntity : class,new()
{
private readonly CoreContext _db;
public DBService(CoreContext _db)
{
this._db = _db;
}
public void UpdateData(TEntity _entity)
{
this._db.Set<TEntity>().UpdateRange(_entity);
this._db.SaveChanges();
}
public void GetAllData(TEntity _entity)
{
var x = this._db.Set<TEntity>().Select(o => o).ToList();
}
}
And I Dependency Injection Service Provider in constructor
this.DBProvider = new ServiceCollection()
.AddScoped<IDBAction<DBRepo>, DBService<DBRepo>>()
.AddScoped<DBContext>()
.AddDbContext<CoreContext>(options => options.UseSqlServer(ConnectionString))
.BuildServiceProvider();
last step I Get Services
DBProvider.GetService<IDBAction<DBRepo>>().GetAllData(new UserAccount());
I will get a error message same with title
or I change to
DBProvider.GetService<IDBAction<UserAccount>>().GetAllData(new UserAccount());
I'll get other message
Object reference not set to an instance of an object.'
but the void UpdateData() is can work,
so how to fix GetAllData() problem?
The error simply is because the class you're using here UserAccount has apparently not been added to your context, CoreContext. There should be a property there like:
public DbSet<UserAccount> UserAccounts { get; set; }
Regardless of whether you end up using the generic Set<T> accessor, you still must defined a DbSet for the entity on your context.
That said, you should absolutely not be creating your own service collection inside your repo. Register your context and your repo with the main service collection in Startup.cs and then simply inject your repo where you need it. The DI framework will take care of instantiating it with your context, as long as you have a constructor that takes your context (which you seem to).
And that said, you should ditch the repo entirely. It still requires a dependency on Entity Framework and doesn't do anything but proxy to Entity Framework methods. This is just an extra thing you have to maintain and test with no added benefit.

Ninject: How to resolve collection from object type

Just wanted to know if there is a way bind a type and resolve a collection. I dont know if Ninject can do this out of the box. I'm using MVC4 with Ninject3 so I have the NinjectWebCommon.cs where I register the services. There is nowhere I can get the kernel (I read that it was bad practice to access the kernel from elsewhere, but that can certainly be the solution to this).
For example, I'm having this class:
public class CacheManager
{
public IEnumerable<SelectListItem> Get<T>() where T : INameValue
I want to be able to send
CacheManager.Get<City>
and obtain the CityRepository class.
Is it this you want to do? :
using System.Collections.Generic;
using System.Linq;
using Ninject;
using Ninject.Modules;
using Ninject.Syntax;
public class Temp
{
public interface ICity { }
public class SelectListItem
{
}
public class FooCity : SelectListItem, ICity { }
public class BarCity : SelectListItem, ICity {}
public class CityModule : NinjectModule
{
public override void Load()
{
this.Bind<ICity>().To<FooCity>();
this.Bind<ICity>().To<BarCity>();
}
}
public class CacheManager
{
private readonly IResolutionRoot resolutionRoot;
public CacheManager(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IEnumerable<SelectListItem> Get<T>()
{
return this.resolutionRoot.GetAll<T>().OfType<SelectListItem>();
}
}
}
I'm unclear as to whether you have multiple implementations of T (ICity) or one implementation but several instances (like retrieving a list of city names from the database and creating one instance per name). The later you could solve by a this.Bind>().ToProvider(...) binding.
I ended up doing:
In NinjectWebCommon.cs:
kernel.Bind(typeof(CacheManager))
.ToSelf()
.InSingletonScope();
kernel.Bind<IDataListRepository<Locale>>()
.To<LocaleRepository>();
In CacheManager.cs:
public class CacheManager: IDisposable
{
private IKernel kernel;
public CacheManager(IKernel kernel)
{
this.kernel = kernel;
}
public IEnumerable<T> GetAsEnumerable<T>()
{
var rep = kernel.Get<IDataListRepository<T>>();
return rep.GetAll();
}
I don't know if this is bad-practice (since kernel in theory should only be used in the initialization phase), but I didn't find any other way to do it.
If better options exist, please let me know.

Expose WCF service for derived class with same name in C#

I want to expose as WCF service two set of classes that have the same name. However, when I add the service reference, it only returns one set of the class.
[ServiceContract(Name = "Service1")]
[XmlSerializerFormat]
public interface IService1
{
[OperationContract]
[ServiceKnownType(typeof(S1.Retangle))]
[ServiceKnownType(typeof(S1.Square))]
[ServiceKnownType(typeof(S2.Retangle))]
[ServiceKnownType(typeof(S2.Square))]
string GetShape(Shape shape);
}
//All types are only example
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public abstract class Shape
{
public int Width { get; set; }
public int Height { get; set; }
public string TypeName { get; set; }
}
namespace S1
{
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public class Retangle : Shape
{ }
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public class Square : Shape
{ }
}
namespace S2
{
//[DataContract]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "Namespace=http://tempuri.org/S2")] //can be changed
public class Retangle : Shape
{ }
//[DataContract]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "Namespace=http://tempuri.org/S2")] //can be changed
public class Square : Shape
{ }
}
Any idea would be very much appreciated.
WCF will generate your objects in its own namespace for use client side but your not forced to use these - you can equally well use your own original objects in the namespaces they were defined by either:
1. Compiling them in a dll and linking to that for both client and sever.
2. If you dont want overhead of shared dll just compile them directly into both server and client.
In the generated proxy code you just need to replace the WCF namespace tags with your own org namespaces so they resolve to your objects and the client side WCF generated ones are ignored.

Bundling a list of entities into a component

With FluentNHibernate I have mapped a UserPreference entity which references the GeneralPreference, GeneralPreferenceOption, and Profile entities:
public class UserPreference
{
public virtual long Id { get; set; }
public virtual Profile Profile { get; set; }
public virtual GeneralPreference Preference { get; set; }
public virtual GeneralPreferenceOption Value { get; set; }
}
It's easy enough to map a list of UserPreference on my Profile entity, but what I actually would like to do is wrap this list inside another class so that I can simplify operations concerning a user's given preferences:
public class Preferences
{
public IList<UserPreferences> UserPreferences{get;set;}
public Language Language {
{
//look up the language preference here
}
}
This kind of feels like a Component, but Components were not created for this type of scenario. Does anyone have any pointers on how I might map this?
I figured out a way to do this by mapping a private property on my Profile Entity. Using the techniques from the Fluent NHibernate wiki on mapping private properties (http://wiki.fluentnhibernate.org/Fluent_mapping_private_properties) I map a collection of UserPreference on my Profile Entity. Then I create another class PropertyHandler which takes an IEnumerable as a constructor parameter and make an instance of this a public property on Profile as well:
public class Profile
{
private PreferenceHandler _preferenceHandler;
get { return _preferenceHandler ?? (_preferenceHandler = new PreferenceHandler(UserPreferences)); }
private IEnumerable<UserPreference> UserPreferences { get; set; }
public static class Expressions
{
public static readonly Expression<Func<Profile, IEnumerable<UserPreference>>> UserPreferences = x => x.UserPreferences;
}
}
Notice the nested static class. It's used to enable mapping of a private property with FluentNHibernate.
The mapping class looks something like this:
public class ProfileMappings : ClassMap<Profile>
{
public ProfileMappings()
{
//... other mappings
HasMany(Profile.Expressions.UserPreferences);
}
}
I can now use the PreferenceHandler class to create helper methods over my collection of UserPreference.
An alternative is to build extension methods for IEnumberable. This works, but I decided not to do this because
1) I'm not really extending the IEnumerable functionality and
2) my helper methods disappear inamongst all the other IEnumerable extension methods making the whole thing a bit cluttered.

Getting error "Association references unmapped class" when using interfaces in model

I'm trying to use the automap functionality in fluent to generate a
DDL for the following model and program, but somehow I keep getting
the error "Association references unmapped class: IRole" when I call
the GenerateSchemaCreationScript method in NHibernate. When I replace
the type of the ILists with the implementation of the interfaces (User
and Role) everything works fine. What am I doing wrong here? How can I
make fluent use the implemented versions of IUser and IRole as defined
in Unity?
public interface IRole
{
string Title { get; set; }
IList<IUser> Users { get; set; }
}
public interface IUser
{
string Email { get; set; }
IList<IRole> Roles { get; set; }
}
public class Role : IRole
{
public virtual string Title { get; set; }
public virtual IList<IUser> Users { get; set; }
}
public class User : IUser
{
public virtual string Email { get; set; }
public virtual IList<IRole> Roles { get; set; }
}
I use the following program to generate the DDL using the
GenerateSchemaCreationScript in NHibernate:
class Program
{
static void Main(string[] args)
{
var ddl = new NHibernateSessionManager();
ddl.BuildConfiguration();
}
}
public class NHibernateSessionManager
{
private ISessionFactory _sessionFactory;
private static IUnityContainer _container;
private static void InitContainer()
{
_container = new UnityContainer();
_container.RegisterType(typeof(IUser), typeof(User));
_container.RegisterType(typeof(IRole), typeof(Role));
}
public ISessionFactory BuildConfiguration()
{
InitContainer();
return
Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
.ConnectionString("ConnectionString"))
.Mappings(m => m.AutoMappings.Add(
AutoMap.AssemblyOf<IUser>()))
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
private void BuildSchema(Configuration cfg)
{
var ddl = cfg.GenerateSchemaCreationScript(new
NHibernate.Dialect.MsSql2008Dialect());
System.IO.File.WriteAllLines("Filename", ddl);
}
}
I am in the same situation as you. Having used the ClassMap before I know you can do this with Fluent but I had never used the AutoMapping feature before. I have successfully been able to do a one to one mapping with the AutoMapper using an IReferenceConvention (see previous SO post).
I have now hit the same problem as you where I have a one to many mapping which I am now having a problem with. There is an IHasManyConvention interface which I have started to look at but have had no luck as of yet.
Just because some thing is hard to do it doesn't make it wrong, mapping to interfaces defiantly has value and can easily be done in the raw nHibernate mapping files or by using Fluents ClassMap mapping files. I think once people start do more with AutoMapping feature there will be more blog posts.
EDIT
I have found an interim solution using an IAutoMappingOverride. Below is a rough example of what you need.
public class RoleAutoMappingOverride : IAutoMappingOverride<Role>
{
public void Override(AutoMapping<Role> mapping)
{
mapping.HasMany<User>( x => x.Users ).KeyColumn( "User_id" );
}
}
EDIT
A college of mine has worked out a better solution that uses conventions instead of the override. This covers how to do a single class but if you look at the SO post I mentioned before you can see how this could be made generic.
public class Foo : IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
if (instance.ChildType == typeof(Role))
{
instance.Relationship.CustomClass<User>();
}
}
}
EDIT
I have now turned this and my other post into a blog post:
http://bronumski.blogspot.com/2011/01/making-fluent-nhibernate-automapper.html
You can't provide an interface as the type T in AssemblyOf<T>, you need to provide a concrete type. Or you could use the method that accepts an assemply:
.Mappings(m => m.AutoMappings.Add(
AutoMap.Assembly(myAssembly)))
Edit: The problem is that your classes contain collections of interface types instead of class type. I don't know if it's possible to automap interfaces in this manner. Also, I think there's rarely any value in using interfaces to specify domain objects.