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; }
}
Related
<I have two classes with too many fields . which are basically the Model of MVC . I want to create a third class which take few fields from both 1st,2nd by inheritance but not all the fields of 1st and 2nd class is it possible by inheritance .I want to
make a new class without declare field in it
public class OpeningBalanceLiteModel
{
public Int64 LedgerId { get; set; }
public String LedgerCode { get; set; }
public Int64? ParentLedgerId { get; set; }
public Decimal OpeningBalance { get; set; }
public Boolean? Status { get; set; }
public Int32? LedgerCategoryId { get; set; }
public Byte Is_Active { get; set; }
public Byte Is_Deleted { get; set; }
}
public class DrCrDetailLiteModel
{
public Int32 Id { get; set; }
public Int32 TransactionTypeId { get; set; }
public Int32? AmountType { get; set; }
public Decimal? Amount { get; set; }
public String VoucherNarration { get; set; }
public Int32 FinancialYearId { get; set; }
public Int64 CompanyId { get; set; }
public Decimal? SubsidiaryId { get; set; }
public Decimal? LocationBranchId { get; set; }
public Decimal? DivisionId { get; set; }
public Int32? DepartmentId { get; set; }
public Int32? ProjectId { get; set; }
public Int32? ProjectEstimationId { get; set; }
public Boolean? IsAdvancePayment { get; set; }
public Boolean? IsHiddenFromSourceLedger { get; set; }
public Boolean? IsReversed { get; set; }
}
public class OpeningBalanceDrCrMurg
{
}```
* i wan to add 3 fields of both class by inheritance
We commonly calls inheritance a "is a" relation ship, an apple is a fruit. If you do not include all properties it is not a "is a" relationship. Is all fruits have a color, then an apple must have a color.
Moreover, c# does not support multiple inheritance. You could inherit from multiple interfaces, and that would also allow you to use explicit interface implementation to hide properties unless a reference of the interface type is used. But I get the impression that your goal is implementation inheritance.
My recommendation would be to use Composition instead of inheritance. Group your properties in to logical groups, and compose these models, for example:
public class LedgerModel{
public Int64 LedgerId { get; set; }
public String LedgerCode { get; set; }
public Int64? ParentLedgerId { get; set; }
}
public class OpeningBalanceLiteModel{
LedgerModel {get;set;}
...
}
That should allow finer grained control to allow you to include any combination of property-groups in your classes.
you should create a Base Class ex:
public class BaseClass
{
public int Id1 { get; set; }
public int Id2 { get; set; }
public int Id3 { get; set; }
}
public class childrenClass1 :BaseClass
{
...
}
public class childrenClass2:BaseClass
{
...
}
Now children class1 and 2 have Id1/Id2/Id3
I have these two objects:
public class BaseModule
{
public long BaseModuleID { get; set; }
public string ModuleName { get; set; }
public bool CanOpen { get; set; }
public bool CanConfigure { get; set; }
}
public class ActiveModule
{
public long ActiveModuleID { get; set; }
public long BaseModuleID { get; set; }
public BaseModule Module { get; set; }
}
The BaseModule is in a 1:1 relation to the ActiveModule object and ActiveModule is a wrapper for BaseModule.
Now I want to save ActiveModule but it says that the column BaseModuleID has no default value for it. But in my object the child BaseModule.
I would know expect that the value of the child will be chosen to insert into the column.
Am I missing anything here or just dont really understand how cascading is done in Dapper?
You need the foreign key attribute I think:
public class ActiveModule
{
public long ActiveModuleID { get; set; }
[ForeignKey("Module")]
public long BaseModuleID { get; set; }
public BaseModule Module { get; set; }
}
public class BaseModule
{
public long BaseModuleID { get; set; }
public bool CanConfigure { get; set; }
public bool CanOpen { get; set; }
public string ModuleName { get; set; }
}
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.
public interface IBase
{
int Id { get; set; }
}
public interface IDerivedA : IBase
{
int Name { get; set; }
int Quantity { get; set; }
}
public interface IDerivedB : IBase
{
string Name { get; set; }
IEnumerable<IDerivedA> DerivedBs { get; set; }
}
And here is an implementation for a class which will be serialized, but I'm getting compilation error when I try to use DerivedASerialize class which is a derived class from IDerivedA interface
[MessagePack.Union(0, typeof(DerivedASerialize))]
[MessagePack.Union(1, typeof(DerivedBSerialize))]
[MessagePack.MessagePackObject(true)]
public class BaseSerialize : IBase
{
public int Id { get; set; }
public bool IsNull { get;set; }
}
[MessagePack.MessagePackObject(true)]
public class DerivedASerialize : BaseSerialize, IDerivedA
{
public int Name { get; set; }
public int Quantity { get; set; }
}
[MessagePack.MessagePackObject(true)]
public class DerivedBSerialize : BaseSerialize, IDerivedB
{
public string Name { get; set; }
public IEnumerable<DerivedASerialize> DerivedBs { get; set; }
}
Is there any work around? as I can only serialize classes.
And I would like to have another class which also derive from the same interface and have different properties
Using neuec's MessagePack.
Edit: Add serialization logic to classes.
If you require two different "Name" fields you can use explicit interface implementation:
public class DerivedBSerialize : BaseSerialize, IDerivedB
{
public string Name { get; set; }
public IEnumerable<DerivedASerialize> DerivedBs { get; set; }
string IDerivedB.Name { get; set; }
IEnumerable<IDerivedA> IDerivedB.DerivedBs { get; set; }
}
If you require just a single "Name" field - you can raise it to "IBase", or create another interface -
interface INameable { string Name {get; set;} }
I'm trying to map these three classes to one EF table. In this scenario, my base class actually has a base Entity class, is this causing my issue? I'm not finding any examples that cover a scenario where the default behavior isn't handled properly.
Base Class:
public abstract class Connection : Entity
{
public override int Id { get; set; }
public ContactEnums.ConnectionType Type { get; set; }
public string Value { get; set; }
}
Child Classes:
public class BusinessConnection : Connection
{
[ForeignKey("Business")]
public int BusinessId { get; set; }
public Business Business { get; set; }
}
public class ContactConnection : Connection
{
[ForeignKey("Contact")]
public int ContactId { get; set; }
public Contact Contact { get; set; }
}
Entity Base class:
public abstract class Entity : EqualityAndHashCodeProvider<Entity, int>
{
public override int Id { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedDate { get; set; }
[NotMapped]
public ObjectState ObjectState { get; set; }
}