C# 如何在OData中禁用OpenTypes的不存在属性

C# 如何在OData中禁用OpenTypes的不存在属性,c#,odata,C#,Odata,我使用的是开放类型: public class Student { public Guid Id { get; set; } public string Name { get; set; } public IBackpack Backpack { get { return new Backpack() { Id = Guid.NewGuid(

我使用的是开放类型:

public class Student
    {
        public Guid Id { get; set; }

        public string Name { get; set; }

        public IBackpack Backpack
        {
            get
            {
                return new Backpack() { Id = Guid.NewGuid() };
            }
            set
            {

            }
        }

        Dictionary<string, object> interfaces;
        public Dictionary<string, object> Interfaces
        {
            get
            {
                if (interfaces == null)
                {
                    interfaces = new Dictionary<string, object>
                    {
                        { "Backpack", this.Backpack as Backpack }
                    };
                }
                return interfaces;
            }
            set
            {
            }
        }
    } 

如何在open types dictionary上不存在属性时返回错误?

因此,问题是在Github中产生的: 然而,他们说这是意料之中的。我找到了解决此问题的方法:

我在CreateResource方法中添加了自定义资源序列化程序并验证现有属性:

public class CustomODataResourceSerializer : ODataResourceSerializer
{
    public CustomODataResourceSerializer(ODataSerializerProvider serializerProvider) : base(serializerProvider)
    {

    }

    public override ODataResource CreateResource(SelectExpandNode selectExpandNode, ResourceContext resourceContext)
    {
        var resource = base.CreateResource(selectExpandNode, resourceContext);

        if (selectExpandNode.SelectedDynamicProperties?.Any() == true)
        {
            foreach (var dynamicProperty in selectExpandNode.SelectedDynamicProperties)
            {
                if (!resource.Properties.Any(s => s.Name == dynamicProperty) && resourceContext.DynamicComplexProperties?.Any(s => s.Key == dynamicProperty) != true)
                {
                    throw new InvalidOperationException($"Cannot find property '{dynamicProperty}' on '{resource.TypeName}' entity");
                }
            }
        }

        return resource;
    }

    public override void AppendDynamicProperties(ODataResource resource, SelectExpandNode selectExpandNode, ResourceContext resourceContext)
    {
        if (selectExpandNode.SelectedDynamicProperties?.Any() == true)
        {
            base.AppendDynamicProperties(resource, selectExpandNode, resourceContext);
        }
    }
}
它工作得很好,但是在过滤查询中我遇到了这种问题。因此,我添加了验证方法:

 void ValidateOpenType(QueryNode expression)
        {
            if (expression is BinaryOperatorNode operatorNode)
            {
                ValidateOpenType(operatorNode.Left);
                ValidateOpenType(operatorNode.Right);
            }
            else if (expression is ConvertNode convertNode)
            {
                ValidateOpenType(convertNode.Source);
            }
            else if (expression is SingleValueFunctionCallNode functionCallNode)
            {
                foreach (var queryNode in functionCallNode.Parameters)
                {
                    ValidateOpenType(queryNode);
                }
            }
            else if (expression is SingleValuePropertyAccessNode singleValueProperty && !string.IsNullOrEmpty(singleValueProperty.Property?.Name))
            {
                if (singleValueProperty.Source is SingleNavigationNode navigationNode)
                {
                    ThrowExceptionWhenPropertyDoesNotExists(singleValueProperty.Property.Name, navigationNode.NavigationSource.Name);
                }
                else
                {
                    ThrowExceptionWhenPropertyDoesNotExists(singleValueProperty.Property.Name, typeof(TEntity).Name);
                }
            }
            else if (expression is SingleValueOpenPropertyAccessNode valueOpenPropertyAccessNode)
            {
                if (valueOpenPropertyAccessNode.Source is SingleNavigationNode navigationNode)
                {
                    ThrowExceptionWhenPropertyDoesNotExists(valueOpenPropertyAccessNode.Name, navigationNode.NavigationSource.Name);
                }
                else
                {
                    ThrowExceptionWhenPropertyDoesNotExists(valueOpenPropertyAccessNode.Name, typeof(TEntity).Name);
                }
            }
        }

        void ThrowExceptionWhenPropertyDoesNotExists(string propertyName, string entityName)
        {
            if (ModelClasses.Any(t => t.Name == entityName && t.GetProperty(propertyName) == null))
            {
                throw new InvalidOperationException($"Could not find a property named '{propertyName}' on '{entityName}' entity");
            }
        }
上课:

List<Type> modelClasses;
        public List<Type> ModelClasses
        {
            get
            {
                if (modelClasses == null)
                {
                    modelClasses = GetClasses("ODataCoreTest");
                }
                return modelClasses;
            }
        }

        static List<Type> GetClasses(string nameSpace)
        {
            Assembly asm = Assembly.GetExecutingAssembly();

            List<Type> namespacelist = new List<Type>();
            List<Type> classlist = new List<Type>();

            foreach (Type type in asm.GetTypes())
            {
                if (type.Namespace == nameSpace)
                    namespacelist.Add(type);
            }

            foreach (Type classType in namespacelist)
                classlist.Add(classType);

            return classlist;
        }
列出模型类;
公共列表模型类
{
得到
{
if(modelClasses==null)
{
modelClasses=GetClasses(“ODataCoreTest”);
}
返回模型类;
}
}
静态列表GetClass(字符串命名空间)
{
Assembly asm=Assembly.getExecutionGassembly();
列表名称空间列表=新列表();
List classlist=新列表();
foreach(在asm.GetTypes()中键入Type)
{
if(type.Namespace==名称空间)
名称空间列表。添加(类型);
}
foreach(名称空间列表中的类型classType)
classlist.Add(classType);
返回类列表;
}
用法:

[HttpGet]
        public IActionResult Get(ODataQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken)
        {
            if (queryOptions.Filter?.FilterClause != null)
            {
                ValidateOpenType(queryOptions.Filter.FilterClause.Expression);
            }
            var res = new List<Student>() { CreateNewStudent() };

            return Ok(res);
        }
[HttpGet]
公共IActionResult Get(ODataQueryOptions查询选项、取消令牌取消令牌)
{
if(queryOptions.Filter?.FilterClause!=null)
{
ValidatePenType(queryOptions.Filter.FilterClause.Expression);
}
var res=new List(){CreateNewStudent()};
返回Ok(res);
}
List<Type> modelClasses;
        public List<Type> ModelClasses
        {
            get
            {
                if (modelClasses == null)
                {
                    modelClasses = GetClasses("ODataCoreTest");
                }
                return modelClasses;
            }
        }

        static List<Type> GetClasses(string nameSpace)
        {
            Assembly asm = Assembly.GetExecutingAssembly();

            List<Type> namespacelist = new List<Type>();
            List<Type> classlist = new List<Type>();

            foreach (Type type in asm.GetTypes())
            {
                if (type.Namespace == nameSpace)
                    namespacelist.Add(type);
            }

            foreach (Type classType in namespacelist)
                classlist.Add(classType);

            return classlist;
        }
[HttpGet]
        public IActionResult Get(ODataQueryOptions<TEntity> queryOptions, CancellationToken cancellationToken)
        {
            if (queryOptions.Filter?.FilterClause != null)
            {
                ValidateOpenType(queryOptions.Filter.FilterClause.Expression);
            }
            var res = new List<Student>() { CreateNewStudent() };

            return Ok(res);
        }