Add typed procedure descriptors and Exec invoker

This commit is contained in:
2026-02-27 16:27:49 +01:00
parent 9ce10273f1
commit 416404f8d1
7 changed files with 410 additions and 23 deletions

View File

@@ -0,0 +1,100 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012-2026, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Linq;
using DynamORM.Mapper;
using DynamORM.Objects;
namespace DynamORM.Helpers
{
internal sealed class DynamicProcedureDescriptor
{
public Type ProcedureType { get; set; }
public Type ArgumentsType { get; set; }
public Type ResultType { get; set; }
public string ProcedureName { get; set; }
public string ResultName { get; set; }
internal static DynamicProcedureDescriptor Resolve(Type procedureType)
{
if (procedureType == null)
throw new ArgumentNullException("procedureType");
Type current = procedureType;
Type argumentsType = null;
Type resultType = null;
while (current != null && current != typeof(object))
{
if (current.IsGenericType)
{
Type genericDefinition = current.GetGenericTypeDefinition();
Type[] genericArguments = current.GetGenericArguments();
if (genericDefinition == typeof(Procedure<>) && genericArguments.Length == 1)
{
argumentsType = genericArguments[0];
break;
}
if (genericDefinition == typeof(Procedure<,>) && genericArguments.Length == 2)
{
argumentsType = genericArguments[0];
resultType = genericArguments[1];
break;
}
}
current = current.BaseType;
}
if (argumentsType == null)
throw new InvalidOperationException(string.Format("Type '{0}' is not a typed procedure descriptor.", procedureType.FullName));
if (!typeof(IProcedureParameters).IsAssignableFrom(argumentsType))
throw new InvalidOperationException(string.Format("Procedure descriptor '{0}' declares argument type '{1}' that does not implement IProcedureParameters.", procedureType.FullName, argumentsType.FullName));
ProcedureAttribute attr = procedureType.GetCustomAttributes(typeof(ProcedureAttribute), true)
.Cast<ProcedureAttribute>()
.FirstOrDefault();
string name = attr != null && !string.IsNullOrEmpty(attr.Name) ? attr.Name : procedureType.Name;
string owner = attr != null ? attr.Owner : null;
return new DynamicProcedureDescriptor
{
ProcedureType = procedureType,
ArgumentsType = argumentsType,
ResultType = resultType,
ProcedureName = string.IsNullOrEmpty(owner) ? name : string.Format("{0}.{1}", owner, name),
ResultName = name
};
}
}
}