Common interface usage in ctor for some classes - c#

In my CollectionService class i want to be able to use either DatabaseWatchService or RemoteFilesWatchService therefore I used IWatchService<IEntity> watchService parameter which should be common for both. Nevertheless in DoIt() when i try to use either one of the class i am having following error:
Cannot implicitly convert type 'RemoteFilesWatchService' to
'IWatchService'. An explicit conversion exists (are you missing a
cast?)
How to fix that to able to use in CollectionService either one mentioned class or another.
This is the full code:
public interface IWatch
{
void Watch();
}
public interface IWatchService<TDataEntity> where TDataEntity : IEntity
{
INotificationFactory NotificationFactory { get; }
ObservableCollection<TDataEntity> MatchingEntries { get; set; }
}
public interface IDatabaseWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IDatabaseEntity
{
IDatabaseRepository<IDbManager> DatabaseRepository { get; }
}
public interface IRemoteFilesWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IFileEntity
{
List<string> ExistingRemoteFiles { get; set; }
List<RemoteLocation> RemoteLocations { get; set; }
IWinScpOperations RemoteManager { get; set; }
IRemoteFilesRepository<IDbManager, TDataEntity> RemoteFilesRepository { get; }
}
public class RemoteFilesWatchService : IRemoteFilesWatchService<IFileEntity>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<IFileEntity> MatchingEntries { get; set; }
public List<string> ExistingRemoteFiles { get; set; }
public List<RemoteLocation> RemoteLocations { get; set; }
public IWinScpOperations RemoteManager { get; set; }
public IRemoteFilesRepository<IDbManager, IFileEntity> RemoteFilesRepository { get; }
public RemoteFilesWatchService(IWinScpOperations remoteOperator,
IRemoteFilesRepository<IDbManager, IFileEntity> remoteFilesRepository,
INotificationFactory notificationFactory)
{
RemoteManager = remoteOperator;
RemoteFilesRepository = remoteFilesRepository; //csv, xml or other repo could be injected
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class DatabaseWatchService : IDatabaseWatchService<DatabaseQuery>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<DatabaseQuery> MatchingEntries { get; set; }
public IDatabaseRepository<IDbManager> DatabaseRepository { get; }
public DatabaseWatchService(IDatabaseRepository<IDbManager> databaseRepository,
INotificationFactory notificationFactory)
{
DatabaseRepository = databaseRepository;
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class CollectionService
{
private IWatchService<IEntity> _watchService;
public CollectionService(IWatchService<IEntity> watchService)
{
_watchService = watchService;
}
}
class Run
{
void DoIt()
{
IWatchService<IEntity> fileWatcherServiceCsv = new RemoteFilesWatchService(new WinScpOperations(),
new RemoteCsvFilesRepository(new DbManager(ConnectionDbType.MySql)),
new NotificationFactory());
var coll1 = new CollectionService(fileWatcherServiceCsv);
}
}
public interface IEntity
{
}
public interface IFileEntity : IEntity
{
int Id { get; set; }
string Name { get; set; }
bool IsActive { get; set; }
bool RemoveFromSource { get; set; }
string DestinationFolder { get; set; }
RemoteLocation RemoteLocation { get; set; }
}
public interface IDatabaseEntity : IEntity
{
}
public class CsvFile : IFileEntity
{
public int ColumnHeader { get; set; }
public int ColumnsCount { get; set; }
public string Separator { get; set; }
public int ValuesRowStartposition { get; set; }
public int ColumnRowPosition { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
}
public class XmlFile : IFileEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
public string SubNode { get; set; }
public string MainNode { get; set; }
}

Rather than having IWatchService expose a concrete type, I'd suggest instead having it require reimplementation of those interfaces from ObservableCollection that you actually want the consumers to use (or move those onto another interface and have that be what MatchingEntries returns).
Here I've guessed that the consumers want the events that the observable collection raises and to be able to enumerate the collection and that's all, which means we can a) implement those interfaces and b) make the interface covariant:
public interface IWatchService<out TDataEntity> :
INotifyCollectionChanged,
INotifyPropertyChanged,
IEnumerable<TDataEntity>
where TDataEntity : IEntity
{
INotificationFactory NotificationFactory { get; }
}
Now, if the implementations choose to use an ObservableCollection and just use simple wrappers to implement those interfaces or choose to satisfy the interface in some other way has been move back into an implementation decision.

Related

Mapping Service Class with two Class to DTO Class with properties

I have a service Class list with two Class inside:
public class ParentClass
{
public ChildClass A { get; set; }
public ChildClass2 B { get; set; }
}
public class ChildClass
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ChildClass2
{
public string Color { get; set; }
public string Nick { get; set; }
}
And I would want mapping with AutoMapper into list that have the same properties that Child's Class:
public class DTOClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public string Nick { get; set; }
}
It work fine:
My config:
Mapper.CreateMap<ChildClass, DTOClass>();
Mapper.CreateMap<ChildClass2, DTOClass>();
My code:
List<ParentClass> listParentClass = getListParentClass();
List<DTOClass> listDtoClass = new List<DTOClass>();
ParentClass dtoClass = new ParentClass();
foreach (var parentClass in listParentClass)
{
dtoClass = AutoMapper.Mapper.Map<ChildClass, DTOClass >(parentClass.A);
AutoMapper.Mapper.Map<ChildClass2, DTOClass >(parentClass.B, dtoClass);
listDtoClass.Add(dtoClass);
}
Would I like to remove the foreach, can I?
I searched about Mapping with Child's Class, Mapping with multiple Class to one Class, no success.
I tried configurate it with ForAllMembers, but not work:
Mapper.CreateMap<ParentClass, DTOClass>()
.ForAllMembers(op => op.MapFrom(s => Mapper.Map<ChildClass, DTOClass>(s.A)));
I'm not especialist into AutoMapper, if sameone could help me. I would appreciate.
You can do this:
public class ParentClass
{
public ChildClass A { get; set; }
public ChildClass2 B { get; set; }
}
public class ChildClass
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ChildClass2
{
public string Color { get; set; }
public string Nick { get; set; }
}
public class DTOClass
{
public int AId { get; set; }
public string AName { get; set; }
public string BColor { get; set; }
public string BNick { get; set; }
}
Your mapping:
cfg.CreateMap<ChildClass, DTOClass>();
cfg.CreateMap<ChildClass2, DTOClass>();
cfg.CreateMap<ParentClass, DTOClass>();
Your example:
List<ParentClass> listParentClass = getListParentClass();
//List<DTOClass> listDtoClass = new List<DTOClass>();
var listDtoClass = AutoMapper.Mapper.Map<List<DTOClass>>(listParentClass);

How to specify a class that may contain another class

I want to create a class that have a class but this second class may be different each time the first class is called. For example:
public class ServerResponseObject
{
public string statusCode { get; set; }
public string errorCode { get; set; }
public string errorDescription { get; set; }
public Object obj { get; set; }
public ServerResponseObject(Object obje)
{
obj = obje;
}
}
public class TVChannelObject
{
public string number { get; set; }
public string title { get; set; }
public string FavoriteChannel { get; set; }
public string description { get; set; }
public string packageid { get; set; }
public string format { get; set; }
}
public class ChannelCategoryObject
{
public string id { get; set; }
public string name { get; set; }
}
How can I do it to call the ServerResponseObject with different objects each time, once with TVChannelObject and once with ChannelCategoryObject?
What you're looking for is a generic type parameter:
public class ServerResponseObject<T>
{
public ServerResponseObject(T obj)
{
Obj = obj;
}
public T Obj { get; set; }
}

System.ArgumentException in valueinjecter when mapping same objects

I have a class:
public class LotInfo
{
public string lotn { get; set; }
public string imlitm { get; set; }
public string imdsc { get; set; }
public string wplotn { get; set; }
public int wptrdj { get; set; }
public DateTime wptrdj_d { get; set; }
public string wplitm { get; set; }
public int wptrqt { get; set; }
public string wpkyfn { get; set; }
public int wpdoco { get; set; }
public string iolitm { get; set; }
public string iodcto { get; set; }
public int iodoco { get; set; }
public int ioub04 { get; set; }
}
I have 2 instances.
Object1 and Object2
I want to inject object2 -> object1 for specific properties.
So i have overridden the Match method like this:
public class LotInfoInject : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name.StartsWith("io");
}
}
and i am using the injecter like this:
object1.InjectFrom(object2);
I cant figure out why i am getting the exception.
{"Object of type 'System.String' cannot be converted to type
'System.Int32'."}
If i DONT override the Match method it works but i am getting properties that i dont want replaced from object1
any ideas?
You're trying to put iolitm (string) in iodoco (int).
Try like this:
public class LotInfoInject : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name.StartsWith("io")
&& c.SourceProp.Name == c.TargetProp.Name;
}
}

How to use a DbSet<T> with a generic type

I have an interface:
public interface ILanguageEntity
{
int Id { get; set; }
string Name { get; set; }
string Code { get; set; }
string Culture { get; set; }
string LocalName { get; set; }
bool IsRightToLeft { get; set; }
}
And I've implemented that as a Entity like this:
public class LanguageEntity : ILanguageEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Culture { get; set; }
public string LocalName { get; set; }
public bool IsRightToLeft { get; set; }
}
In my service I want to have a property for this entity which returns its DbSet like this:
public class LanguageService : ILanguageService
{
public ApplicationContext Context { get; set; }
public DbSet<ILanguageEntity> DbSet { get { return Context.Set<LanguageEntity>(); } }
}
But it's not possible because I'm returning a DbSet<LanguageEntity> type while I must return a DbSet<ILanguageEntity> type as compiler says. What should I do?
well i assume that ApplicationContext should have atleast one ILanguageEntity DbSet
Here is what i came up with :
public class LanguageService : ILanguageService
{
public ApplicationContext Context { get; set; }
public DbSet<ILanguageEntity> DbSet
{
get
{
return Context.LanguageEntities;
}
set
{
throw new NotImplementedException();
}
}
}
public class ApplicationContext : DbContext
{
public DbSet<ILanguageEntity> LanguageEntities { get; set; }
}
public interface ILanguageService
{
DbSet<ILanguageEntity> DbSet { get; set; }
}

Class property defined as an object that implements interface

I have a set of POCO classes which implement IConnectable and IEntity.
In one of the classes, Connection, I want two properties that are defined as objects that implement IConnectable.
public interface IConnectable
{
string Name { get; set; }
string Url { get; set; }
}
And my connection class
public partial class Connection : IEntity
{
public int Id { get; set; }
public T<IConnectable> From { get; set; }
public T<IConnectable> To { get; set; }
public ConnectionType Type { get; set; }
public double Affinity { get; set; }
public DateTimeOffset CreatedOn { get; set; }
}
I know I can't use generic objects are properties -- so is there any other way to do this?
It's most likely appropriate to just not have generics at all :
public partial class Connection : IEntity
{
public int Id { get; set; }
public IConnectable From { get; set; }
public IConnectable To { get; set; }
public ConnectionType Type { get; set; }
public double Affinity { get; set; }
public DateTimeOffset CreatedOn { get; set; }
}
If it's important that instances of Connection return types of something more derived then you'll need to make the whole class generic:
public partial class Connection<T> : IEntity
where T : IConnectable
{
public int Id { get; set; }
public T From { get; set; }
public T To { get; set; }
public ConnectionType Type { get; set; }
public double Affinity { get; set; }
public DateTimeOffset CreatedOn { get; set; }
}
If you need to be able to have two different IConnectable types for the two properties, then you need to generic parameters:
public partial class Connection<TFrom, TTo> : IEntity
where TFrom : IConnectable
where TTo : IConnectable
{
public int Id { get; set; }
public TFrom From { get; set; }
public TTo To { get; set; }
public ConnectionType Type { get; set; }
public double Affinity { get; set; }
public DateTimeOffset CreatedOn { get; set; }
}

Categories