Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserializing to an Interface #253

Open
dthk-cogmatix opened this issue Aug 28, 2021 · 5 comments
Open

Deserializing to an Interface #253

dthk-cogmatix opened this issue Aug 28, 2021 · 5 comments
Labels
bug driver-issue Issue caused by the official MongoDB driver

Comments

@dthk-cogmatix
Copy link

I'm knocking my head around for something I think should work, but it's not.

I have a class with a list of interfaces (events).

public myclass
{
List Events;
}

Mongoframework can serialize the events and store them properly with a discriminator/type.

However, I can't get it to deserialize back to MyClass.

I've tried BsonDiscriminator/BsonKnownType/RuntimeTypeDiscovery with no luck.

Is this possible with an interface or only base class?

@Turnerj
Copy link
Member

Turnerj commented Aug 28, 2021

Hey @dthk-cogmatix - sorry that this isn't working properly - can you share more of the class and property? If it is something like:

public class MyClass
{
    public List<SomeOtherObject> Events { get; set; }
}

That should work without any issues. Are you getting any errors etc either or just that the property isn't set?

@dthk-cogmatix
Copy link
Author

dthk-cogmatix commented Aug 28, 2021

Thanks for the quick response. The example you shared definitely works - so long as SomeOtherObject is an object and not an interface.

public class MyClass
{
        private List<INotification> _domainEvents;

//I don't think this matters - but sharing since it is in my implementation
        public List<INotification> DomainEvents {
            get
            {
                return _domainEvents;
            }
            set
            {
                _domainEvents = value;
            }
         }
}

public interface INotification { }

public class ConcreteDomainEvent1 : INotification
{
        public int EntityId { get; private set; }

        public ConcreteDomainEvent1(int entityId)
        {
            EntityId = entityId;
        }
}
public class ConcreteDomainEvent2 : INotification
{
        public int EntityId { get; private set; }

        public ConcreteDomainEvent2(int entityId)
        {
            EntityId = entityId;
        }
}

I don't have issues serializing MyClass. It will create a document in MongoDB no problem, including if there are instances of ConcreteDomainEvent1 or ConcreteDomainEvent2. When storing the document to the database, I get the appropriate discriminator value _t of "ConcreteDomainEvent1" or "ConcreteDomainEvent2." However, when I go to deserialize this object, if there is any value in DomainEvents, it will throw an exception not recognizing the discriminator value. There is where I've manually added the Discriminator to the ConcreteDomainEvent classes to see if that helps, but nothing.

I'm actually a bit confused when it can't recognize the discriminator during deserialization if it added the discriminator during serializing...

@Turnerj
Copy link
Member

Turnerj commented Aug 29, 2021

Hmmm, I can't seem to recreate the issue you're hitting. This is the test case I was trying with:

[TestClass]
public class InterfacesOnProperties : TestBase
{
	interface IExampleInterface
	{
		public string InterfaceDefinedProperty { get; }
	}

	class ExampleImplOne : IExampleInterface
	{
		public string ImplOneProperty { get; }
		public string InterfaceDefinedProperty { get; }

		public ExampleImplOne(string implOneProperty, string interfaceDefinedProperty)
		{
			ImplOneProperty = implOneProperty;
			InterfaceDefinedProperty = interfaceDefinedProperty;
		}
	}

	class ExampleImplTwo : IExampleInterface
	{
		public string ImplTwoProperty { get; set; }
		public string InterfaceDefinedProperty { get; set; }
	}

	class ListOfInterfacesModel
	{
		public string Id { get; set; }
		public List<IExampleInterface> Items { get; set; }
	}

	[TestMethod]
	public void ListOfInterfaces()
	{
		var connection = TestConfiguration.GetConnection();
		var context = new MongoDbContext(connection);
		var dbSet = new MongoDbSet<ListOfInterfacesModel>(context)
		{
			new ListOfInterfacesModel
			{
				Items = new List<IExampleInterface>
				{
					new ExampleImplOne("ImplOne", "ImplOne"),
					new ExampleImplTwo
					{
						ImplTwoProperty = "ImplTwo",
						InterfaceDefinedProperty = "ImplTwo"
					}
				}
			}
		};

		context.SaveChanges();

		var data = dbSet.ToArray();
		Assert.AreEqual(1, data.Length);
		Assert.AreEqual("ImplOne", data[0].Items[0].InterfaceDefinedProperty);
		Assert.AreEqual("ImplOne", (data[0].Items[0] as ExampleImplOne).ImplOneProperty);
		Assert.AreEqual("ImplTwo", data[0].Items[1].InterfaceDefinedProperty);
		Assert.AreEqual("ImplTwo", (data[0].Items[1] as ExampleImplTwo).ImplTwoProperty);
	}
}

That said, what you described sounds similar to an issue I've seen before with MongoDB (see this Jira issue: https://jira.mongodb.org/browse/CSHARP-1907 ). I don't know if they have made any more progress on that issue though.

@dthk-cogmatix
Copy link
Author

CSHARP-1907 is EXACTLY the problem and what is happening. Reading through that, I can see your experience with it as well ;)

Apologies for thinking this was a MongoFramework issue, which is why I somewhat I approached this as: "Should this work?"

This also explains why I couldn't find anything significant with discriminators looking through the framework: it's in the driver.

My naive question: Can you overcome this limitation and behavior within the framework? I was looking at TypeDiscoverySerializer and specifically:


						if (!assembly.IsDynamic)
						{
							foreach (var type in assembly.GetTypes())
							{
								if (type.Name == name && expectedAssignableType.IsAssignableFrom(type))
								{
									AssignableTypes.Add(type);
									return type;
								}
							}
						}

It seems like you're handling the convention names and which serializer here. The driver is incorrectly providing the convention name (in that exact format listed: Namespace.Something.Class, Namespace.Something), but could it just be handled here? I'm sure it's more complicated than this...

@Turnerj Turnerj added bug driver-issue Issue caused by the official MongoDB driver and removed question labels Aug 30, 2021
@Turnerj
Copy link
Member

Turnerj commented Aug 30, 2021

CSHARP-1907 is EXACTLY the problem and what is happening. Reading through that, I can see your experience with it as well ;)

Yep - your issue was familiar as I tried to do something similar a few years back for a project of mine. It was quite an annoying experience!

Apologies for thinking this was a MongoFramework issue, which is why I somewhat I approached this as: "Should this work?"

This also explains why I couldn't find anything significant with discriminators looking through the framework: it's in the driver.

No need to apologise - it could have been an issue with MongoFramework but yeah in this case the issue is the driver.

My naive question: Can you overcome this limitation and behavior within the framework? I was looking at TypeDiscoverySerializer and specifically:


						if (!assembly.IsDynamic)
						{
							foreach (var type in assembly.GetTypes())
							{
								if (type.Name == name && expectedAssignableType.IsAssignableFrom(type))
								{
									AssignableTypes.Add(type);
									return type;
								}
							}
						}

It seems like you're handling the convention names and which serializer here. The driver is incorrectly providing the convention name (in that exact format listed: Namespace.Something.Class, Namespace.Something), but could it just be handled here? I'm sure it's more complicated than this...

It might be possible, yeah. I'd have to do a bit of an investigation to see how I could do it but in theory, it might work. Can't give a solid time frame on when I can get around to that unfortunately - sorry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug driver-issue Issue caused by the official MongoDB driver
Projects
None yet
Development

No branches or pull requests

2 participants