Is there a way to dial down the OData Service reflection provider? - c#

This is a continuation of an issue I'm still experiencing here. I'm trying to prevent the OData reflection provider from trying to expose ALL of the CLR classes in my assembly.
Consider the following CLR class:
public class Foo
{
public Guid FooID { get; set; }
public string FooName { get; set; }
}
And the following class to expose Foo as an IQueryable collection:
public class MyEntities
{
public IQueryable<Foo> Foos
{
get
{
return DataManager.GetFoos().AsQueryable<Foo>();
}
}
}
And the following DataService class:
public class MyDataService : DataService<MyEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Foos", EntitySetRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
This all works hunkey dorey and the DataService can display a collection of Foo. But if change Foo to extend a very simple base object such as:
public class Foo : MyObjectBase
{
public Guid FooID { get; set; }
public string FooName { get; set; }
}
Then (even though I'm only trying to expose 1 collection), the reflection provider grabs ALL objects that extend MyObjectBase, causing loads of errors.
The base class is a simple abstract class that implements a number of interfaces and provides another property such as:
public abstract class MyObjectBase: IDataObject, IDataErrorInfo, INotifyPropertyChanged, IDisposable
{
public virtual Guid ID { get; set; }
}
Even putting IgnoreProperties on any public properties here doesn't help. Is there any way to dial down what the reflection provider is doing?

You could set:
config.SetEntitySetAccessRule("TypeNotAccessible", EntitySetRights.All);
to
config.SetEntitySetAccessRule("TypeNotAccessible", EntitySetRights.None);
On any classes you don't want accessible. I do this using the help of a custom attribute that indicates the rights I want for a particular class. This in combination with looping over all known types (that implement my attribute), makes it possible to do this without explicit code to set each class individually.

I was unable to find a way to dial down the reflection provider with a rich data model. I ended up building a custom provider as indicated here.
If someone provides a way to dial down the reflection provider, I'll accept that answer.

Related

InvalidOperationException: Can't compile a NewExpression with a constructor declared on an abstract class

Getting an error when trying to retrieve objects from mongodb:
InvalidOperationException: Can't compile a NewExpression with a
constructor declared on an abstract class
My class is:
public class App
{
public List<Feature> Features { get; set; }
}
public abstract class Feature
{
public string Name { get; set; }
}
public class ConcreteFeature : Feature
{
public string ConcreteProp { get; set; }
}
Not sure why it is having issues with abstractions. I see, mongodb recorded _t: "ConcreteFeature" type name, it has everything to deserialize it. I have no constructor in abstract class.
Ideas?
I needed to list "KnownTypes" for BsonClassMap to make it work:
BsonClassMap.RegisterClassMap<Feature>(cm => {
cm.AutoMap();
cm.SetIsRootClass(true);
var featureType = typeof(Feature);
featureType.Assembly.GetTypes()
.Where(type => featureType.IsAssignableFrom(type)).ToList()
.ForEach(type => cm.AddKnownType(type));
});
This way you won't need to touch the code even if you add new types as long as they are in 1 assembly. More info here.
1.On Abstract class Use
[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(ConcreteFeature)]
public abstract class Feature
{
public string Name { get; set; }
}
public class ConcreteFeature : Feature
{
public string ConcreteProp { get; set; }
}
You're never going to store your abstract class directly in the database. The whole known types stuff is just if you need the inheritance tree in the type discriminator which is typically overkill. The serializer does need to know about your concrete classes in advance though so the below will suffice.
BsonClassMap.RegisterClassMap<ConcreteFeature>();
Assuming you're going to be adding child classes regularly then you can use reflection and register them that way.

Couple related types together to control use in code using generics

I am trying to limit the use of types by chaining the aggregate IAggregate, the aggregate event IDomainEvent, and Identity together with generics, I have snipped the below code to give context of the issue of what I have got so far.
I have the following interfaces:
public abstract class Identity<T>
{
protected abstract string GetIdentity();
}
public interface IAggregate<T>
{
Identity<T> Identity { get; }
}
public interface IDomainEvent<TIdentity,TIdentity>
where T : Identity<TIdentity>
{
TIdentity Id { get; }
}
I implement with the below:
public class TestUserId : Identity<TestUser>
{
public TestUserId(string name) { Name = name; }
readonly public string Name;
protected override string GetIdentity() => Name.ToLowerInvariant();
}
public class TestUser : IAggregate<TestUser>
{
public TestUser(TestUserId id)
{
Id = id;
var ev = new TestUserCreated()
}
public TestUserId Id { get; }
public Identity<TestUser> Identity => Id;
}
public class TestUserCreated : IDomainEvent<TestUserId, TestUser>
{
public TestUserCreated() { }
public TestUserId Id => throw new NotImplementedException();
}
Then in the command handler, for this event to be used (and for me to be able to obtain the TestUserId which should be member of the domainEvent object).
public interface IDomainEventHandler<TEvent>
{
void Handle(TEvent domainEvent, bool isReplay);
}
That gives me the code:
public class TesterHandler : IDomainEventHandler<TestUser, TestUserCreated>
{
public void Handle(TestUserCreated domainEvent, bool isReplay)
{
// can access the ID (of type TestUserId)
var testUserId = domainEvent.Id;
}
}
So the above TesterHandler is fine exactly how i would want - however the compiler is failing on class TestUserCreated : IDomainEvent<TestUserId, TestUser> with The type TestUserId' cannot be used as type parameter 'TIdentity' in the generic type or method 'IDomainEvent<TIdentity, Type>'. There is no implicit reference conversion from 'TestUserId' to 'Identity<TestUser>'.
What I want is to couple (without OO inheritance) the event to the aggregate, so that it is tied to a specific aggregate type (i.e. specific events are tied to a specific entity, and the entity ID is part of the event type as a field), I want to try and make it impossible to code event handlers for unrelated aggregates.
I am trying to implement but the compiler complains of boxing and implicit casting errors (depending on what i try/guess), in short I am unsure how to code the above.
Given I was unable to create running code as per comments requested (hence the reason for the post) and general complexity, I decided using generics in this way was a bad idea with rationale below.
I currently have code which calls the handler as follows (and this is working fine) passing in the sourceIdentity external to the domainEvent object:
public interface IDomainEventHandler<TIdentity, TEvent>
where TIdentity : IIdentity
where TEvent : IDomainEvent
{
void Handle(TIdentity sourceIdentity, TEvent domainEvent, bool isReplay);
}
I am passing in the aggregate ID external to the IDomainEvent object (and this is desired to keep the events, from an event sourcing perspective, as simple as possible as simple POCO objects without inheritance or involving any framework).
The reason for the question was I just wanted to explore all options with generics (so the domainEvent object could have an interface that would give an ID field) but it started to get complicated quickly, specifically additional template parameters would be required since we are inferring relationships via templates, rather than OO relationships.
Without OO, the relationship would need to be defined somewhere by adding additional types to templates to tie them together interface IDomainEvent<TIdentity,TAggregate,TEvent> and interface IDomainEventHandler<TIdentity, TAggregate, TEvent>, in this case OO inheritance would be preferred and result in way less code.
All this was done to give an interface to obtain the ID, however as if an ID is really needed it can be incorporated in the event as a normal field (without the need for complex OO relationships or templates).
public interface IDomainEvent
{
DateTime OccurredOn { get; set; }
Guid MessageId { get; set; }
}
public class TestUserCreated : IDomainEvent
{
// id can be accessed by whatever needs it by being
// defined explicity within the domain event POCO
// without needing any base class or framework.
public readonly TestUserId Id;
public readonly string Name;
public TestUserCreated(TestUserId id, string name)
{
Id = id;
Name = name;
}
}

Prevent instantiation of MongoDB data model outside of current assembly or prevent misuse

Ive got a mongo database set up and if its designed to use strongly typed objects:
public class Message : IDatabaseObject
{
[DataMember]
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[DataMember]
public string MessageBody { get; set; }
}
The class and all properties need to be public for MongoDB to use it as an object
I was about to make a factory to create a new instance as opposed to creating an instance of Message (duplicating code) each time but then I realised there would be more than one way to create a Message.
Is there a way to prevent direct instantiation of the data object outside of the assembly?
You can't make a private or internal property for serialization in mongo, but you can make the setter of property private or internal (mongo c# driver will take care of private setters for serializing and deserializing).
Make the constructor and setters internal or private (based on your use-case)
public class Message
{
[DataMember]
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; internal set; }
[DataMember]
public string MessageBody { get; internal set; }
internal Message() { }
}
public static class MessageFactory
{
public static Message Create()
{
return new Message();
}
}
You can expose a public factory method like DatabaseObjectFactory.Create<Message>() or Message.Create(), while keeping the constructor internal or even private.
If it is enough that during compile time you can't instanciate the class, Fody might be what you want. Specificially Publicize.Fody.
It allows you to write your class as internal. Compile it. Then have it run as a public class.

Automapper Project From Interface to Concrete Class

I'm trying to perform a mapping between an EF domain object to a DTO object using the Automapper 'Project' method, but am having problems when trying to project from an interface to a concrete class. My EF domain object implements an interface that I use commonly with my lookup tables:
public interface ILookupItem
{
int Id { get; set; }
string Name { get; set; }
}
and here's an example of my domain object:
public partial class ReportType : ILookupItem
{
public int Id { get; set; }
public string Name { get; set; }
}
In my app, I'm using a DTO object which exactly matches the domain object interface:
public class LookupItemModel
{
public static void CreateMapping(IConfiguration configuration)
{
configuration.CreateMap<ILookupItem, LookupItemModel>();
}
public int Id { get; set; }
public string Name { get; set; }
}
I then perform my database query with a call such as:
return DbContext.Query<ReportType>().Project().To<LookupItemModel>();
however on this call Automapper gives an error about missing a required mapping to perform the function:
Missing map from ReportType to LookupItemModel. Create using Mapper.CreateMap<ReportType, LookupItemModel>.
I would have assumed that the mapping could be performed from the interface since all it should need to know are the properties which to pull data for (Id & Name). Am I missing something to be able to perform this projection without creating maps for each concrete implementation of my interface?
Thanks!
I asked in a comment but haven't had a response yet but I'm fairly sure this is your problem so I'm going to go ahead and make it an answer.
You're creating the mapping between ILookupItem and LookupItemModel but you aren't ever calling the method that creates the map - LookupItemModel.CreateMapping().
Before you do the mapping you need to call this method:
LookupItemModel.CreateMapping(your IConfiguration);
return DbContext.Query<ReportType>().Project().To<LookupItemModel>();
That said, instead of setting up your mapping logic inside your models, I would create an AutoMapper configuration class that sets up all your maps. Something like:
public class AutoMapperConfig {
public static CreateMaps() {
CreateLookupItemMaps();
}
public static CreateLookupItemMaps() {
Mapper.CreateMap<ILookupItem, LookupItemModel>();
}
}
Or a cleaner approach would be to use AutoMapper Profiles
And then call AutomapperConfig.CreateMaps() during your app startup and you should be good.

Implementing interfaces in C# .NET

Consider the following interface
public interface ICustomData
{
String CustomData { set; get; }
}
According to MSDN documentation, interfaces members are automatically public.
Lets say I now want to implement my interface:
public class CustomDataHandler : ICustomData
{
}
This would break at compile time, telling me that I have not implemented "CustomData"
This on the otherhand would work:
public class CustomDataHandler : ICustomData
{
public String CustomData { set; get; }
}
My question is: If the member of the interface is automatically public, why MUST I declare the implementation in the class? If the interface declaration is syntactically identical to the class declaration, why can the compiler not infer this automatically from my interface?
EDIT:
My reason for asking. Imagine a scenario where you are building data models, entities etc. I might code some interfaces to these models like so:
public interface IUserAccount
{
Guid Identity { set; get; }
String FirstName { set; get; }
String LastName { set; get; }
String EmailAddress { set; get; }
String Password { set; get; }
}
public interface IUserDataEntry
{
Guid DataIdentity { set; get; }
String DataName { set; get; }
String Data { set; get; }
}
It would be far simpler to construct the models like so:
public class UserAccount : IUserAccount
{
}
public class UserDataEntry : IUserDataEntry
{
}
public class Combined : IUserAccount, IUserDataEntry
{
}
An interface is not there to provide an implementation, it is there to define a contract. This then allows for different implementations to be built which implement it.
They may be syntactically identical, but they mean different things (i.e. they are not semantically identical).
In the interface, the syntax means that an implementing class must expose such a property, with get and set accessors implemented as it sees fit (either explicitly or implicitly). An interface merely defines the outward behaviour that a class must provide; it does not provide any implementation of that behaviour.
In the class, the syntax is an "auto-property", an implementation of the property defined by the interface, and the get and set accessors are implicitly converted into full implementations with a backing field. It looks something like this when it's compiled:
public class CustomDataHandler : ICustomData
{
private string customData;
public string CustomData
{
get
{
return customData;
}
set
{
customData = value;
}
}
}
You are implicitly implementing the interface. In this instance the method signatures of the class must match those of the interface (including accessibility). Ensuring that the methods are marked as public ensures that there are no surprises when looking at the class, for instance:
public class CustomDataHandler : ICustomData
{
String CustomData {get; set}
String PrivateCustomData {get;set;}
}
Even though both properties are declared the same, the CustomData property would be public by virtue of it being declared on the interface even though the declaration looks identical to that of PrivateCustomData. This would be inconsistent and lead to harder to maintain code.
If you do not wish to set the access modifier, you could explicitly implement the interface:
public class CustomDataHandler : ICustomData
{
String ICustomData.CustomData { set; get; }
}
The interface declaration is only specifying the behaviour which the interface defines. In your case, this is a property called CustomData which has a get and set (it is a read/write property) which is of type string.
The class which implements the interface needs to do exactly that - to specify the implementation.
Now in your case, you are using auto implemented properties { get; set; } which looks the same as the interface declaration, however you could also have a backing field and behaviour in your get or set methods.
Here's an example where the CustomData property is private in a derived class:
public class CustomDataHandler : ICustomData
{
private string CustomData { set; get; }
string ICustomData.CustomData { get; set; }
}
But this code compiles, because there is also an explicit implementation of the property.
So, the public modifier is not redundant in this case.
You must explicitly implement it because... You are not limited to implementing it that way. You could use a field, or do something else in your method. An interface is only a method contract that guaranty that this method exist.
public class CustomDataHandler : ICustomData
{
public String CustomData
{
get { return "None of your business!"; }
set { } // Decide to do nothing
}
}
The interface only guaranty this method will exist. Not what you're gonna do with it.
EDIT: As for your edit of your question, you probably seek to have a parent class instead of an interface if you want to implement the method only once for a collection of classes. However, while you can combine interface, you cannot combine parent classes. But, you can add interface at different point of a classes hierarchy.

Categories