This commit is contained in:
grzegorz.russek
2015-05-15 23:11:59 +00:00
parent 8c10309946
commit 31dd69dfc5
64 changed files with 794 additions and 263 deletions

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Some of methods in this code file is based on Kerosene ORM solution

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Some of methods in this code file is based on Kerosene ORM solution

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Some of methods in this code file is based on Kerosene ORM solution

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Some of methods in this code file is based on Kerosene ORM solution

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Some of methods in this code file is based on Kerosene ORM solution

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Some of methods in this code file is based on Kerosene ORM solution

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Some of methods in this code file is based on Kerosene ORM solution

View File

@@ -85,6 +85,7 @@
<Compile Include="DynamicDatabase.cs" />
<Compile Include="DynamicDatabaseOptions.cs" />
<Compile Include="DynamicExtensions.cs" />
<Compile Include="DynamicProcedureInvoker.cs" />
<Compile Include="DynamicQueryException.cs" />
<Compile Include="DynamicSchemaColumn.cs" />
<Compile Include="DynamicTable.cs" />
@@ -102,6 +103,7 @@
<Compile Include="Mapper\DynamicTypeMap.cs" />
<Compile Include="Mapper\IgnoreAttribute.cs" />
<Compile Include="Mapper\TableAttribute.cs" />
<Compile Include="Mapper\DynamicCast.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="DynamicExpando.cs" />
<Compile Include="Helpers\IFinalizerDisposable.cs" />

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@ namespace DynamORM
#region Internal fields and properties
private DbProviderFactory _provider;
private DynamicProcedureInvoker _proc;
private string _connectionString;
private bool _singleConnection;
private bool _singleTransaction;
@@ -118,6 +119,23 @@ namespace DynamORM
/// <summary>Gets the database provider.</summary>
public DbProviderFactory Provider { get { return _provider; } }
/// <summary>Gets the procedures invoker.</summary>
public dynamic Procedures
{
get
{
if (_proc == null)
{
if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
throw new InvalidOperationException("Database connection desn't support stored procedures.");
_proc = new DynamicProcedureInvoker(this);
}
return _proc;
}
}
/// <summary>Gets or sets a value indicating whether
/// dump commands to console or not.</summary>
public bool DumpCommands { get; set; }
@@ -1748,6 +1766,8 @@ namespace DynamORM
}
ClearSchema();
if (_proc != null)
_proc.Dispose();
IsDisposed = true;
}

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -210,7 +210,14 @@ namespace DynamORM
{
if (args != null && args.Count() > 0)
foreach (object item in args)
cmd.AddParameter(database, item);
{
if (item is DynamicExpando)
cmd.AddParameters(database, (DynamicExpando)item);
else if (item is ExpandoObject)
cmd.AddParameters(database, (ExpandoObject)item);
else
cmd.AddParameter(database, item);
}
return cmd;
}
@@ -1413,6 +1420,12 @@ namespace DynamORM
return TypeMap.TryGetNullable(r.GetFieldType(i)) ?? DbType.String;
}
internal static IEnumerable<dynamic> EnumerateReader(this IDataReader r)
{
while (r.Read())
yield return r.RowToDynamic();
}
#endregion IDataReader extensions
#region Mapper extensions

View File

@@ -0,0 +1,236 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012-2015, 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.Collections;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Linq;
using DynamORM.Helpers;
using DynamORM.Mapper;
namespace DynamORM
{
/// <summary>Dynamic procedure invoker.</summary>
/// <remarks>Unfortunately I can use <c>out</c> and <c>ref</c> to
/// return parameters, <see href="http://stackoverflow.com/questions/2475310/c-sharp-4-0-dynamic-doesnt-set-ref-out-arguments"/>.
/// But see example for workaround. If there aren't any return parameters execution will return scalar value.
/// Scalar result is not converted to provided generic type (if any). For output results there is possibility to map to provided class.
/// </remarks><example>You still can use out, return and both way parameters by providing variable prefix:<code>
/// dynamic res = db.Procedures.sp_Test_Scalar_In_Out(inp: Guid.NewGuid(), out_outp: Guid.Empty);
/// Console.Out.WriteLine(res.outp);</code>
/// Prefixes: <c>out_</c>, <c>ret_</c>, <c>both_</c>. Result will contain field without prefix.
/// Here is an example with result class:<code>
/// public class ProcResult { [Column("outp")] public Guid Output { get; set; } }
/// ProcResult res4 = db.Procedures.sp_Test_Scalar_In_Out&lt;ProcResult&gt;(inp: Guid.NewGuid(), out_outp: Guid.Empty) as ProcResult;
/// </code>As you can se, you can use mapper to do job for you.</example>
public class DynamicProcedureInvoker : DynamicObject, IDisposable
{
private DynamicDatabase _db;
internal DynamicProcedureInvoker(DynamicDatabase db)
{
_db = db;
}
/// <summary>This is where the magic begins.</summary>
/// <param name="binder">Binder to invoke.</param>
/// <param name="args">Binder arguments.</param>
/// <param name="result">Binder invoke result.</param>
/// <returns>Returns <c>true</c> if invoke was performed.</returns>
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
// parse the method
CallInfo info = binder.CallInfo;
// Get generic types
IList<Type> types = binder.GetGenericTypeArguments();
Dictionary<string, int> retParams = null;
using (IDbConnection con = _db.Open())
using (IDbCommand cmd = con.CreateCommand())
{
cmd.SetCommand(CommandType.StoredProcedure, binder.Name);
#region Prepare arguments
int alen = args.Length;
if (alen > 0)
{
for (int i = 0; i < alen; i++)
{
object arg = args[i];
if (arg is DynamicExpando)
cmd.AddParameters(_db, (DynamicExpando)arg);
else if (arg is ExpandoObject)
cmd.AddParameters(_db, (ExpandoObject)arg);
else
{
if (info.ArgumentNames.Count > i && !string.IsNullOrEmpty(info.ArgumentNames[i]))
{
bool isOut = info.ArgumentNames[i].StartsWith("out_");
bool isRet = info.ArgumentNames[i].StartsWith("ret_");
bool isBoth = info.ArgumentNames[i].StartsWith("both_");
string paramName = isOut || isRet ?
info.ArgumentNames[i].Substring(4) :
isBoth ? info.ArgumentNames[i].Substring(5) :
info.ArgumentNames[i];
if (isOut || isBoth || isRet)
{
if (retParams == null)
retParams = new Dictionary<string, int>();
retParams.Add(paramName, cmd.Parameters.Count);
}
cmd.AddParameter(
_db.GetParameterName(paramName),
isOut ? ParameterDirection.Output :
isRet ? ParameterDirection.ReturnValue :
isBoth ? ParameterDirection.InputOutput : ParameterDirection.Input,
arg == null ? DbType.String : arg.GetType().ToDbType(), 0, isOut ? DBNull.Value : arg);
}
else
cmd.AddParameter(_db, arg);
}
}
}
#endregion Prepare arguments
#region Get main result
object mainResult = null;
if (types.Count > 0)
{
mainResult = types[0].GetDefaultValue();
if (types[0] == typeof(IDataReader))
mainResult = cmd.ExecuteReader();
else if (types[0].IsGenericEnumerable())
{
Type argType = types[0].GetGenericArguments().First();
if (argType == typeof(object))
using (IDataReader rdr = cmd.ExecuteReader())
mainResult = rdr.EnumerateReader().ToList();
else if (argType.IsValueType)
{
Type listType = typeof(List<>).MakeGenericType(new Type[] { argType });
IList listInstance = (IList)Activator.CreateInstance(listType);
object defVal = listType.GetDefaultValue();
using (IDataReader rdr = cmd.ExecuteReader())
while (rdr.Read())
listInstance.Add(rdr[0] == DBNull.Value ? defVal : argType.CastObject(rdr[0]));
mainResult = listInstance;
}
else
{
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(argType);
if (mapper == null)
throw new InvalidCastException(string.Format("Don't konw what to do with this type: '{0}'.", argType.ToString()));
using (IDataReader rdr = cmd.ExecuteReader())
mainResult = rdr.EnumerateReader().MapEnumerable(argType).ToList();
}
}
else if (types[0].IsValueType)
{
mainResult = cmd.ExecuteScalar();
if (mainResult != DBNull.Value)
mainResult = types[0].CastObject(mainResult);
}
else
{
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(types[0]);
if (mapper == null)
throw new InvalidCastException(string.Format("Don't konw what to do with this type: '{0}'.", types[0].ToString()));
using (IDataReader rdr = cmd.ExecuteReader())
if (rdr.Read())
mainResult = (rdr.ToDynamic() as object).Map(types[0]);
else
mainResult = null;
}
}
else
mainResult = cmd.ExecuteNonQuery();
#endregion Get main result
#region Handle out params
if (retParams != null)
{
Dictionary<string, object> res = new Dictionary<string, object>();
if (mainResult != null)
{
if (mainResult == DBNull.Value)
res.Add(binder.Name, null);
else
res.Add(binder.Name, mainResult);
}
foreach (KeyValuePair<string, int> pos in retParams)
res.Add(pos.Key, ((IDbDataParameter)cmd.Parameters[pos.Value]).Value);
if (types.Count > 1)
{
DynamicTypeMap mapper = DynamicMapperCache.GetMapper(types[1]);
if (mapper != null)
result = mapper.Create(res.ToDynamic());
else
result = res.ToDynamic();
}
else
result = res.ToDynamic();
}
else
result = mainResult;
#endregion Handle out params
}
return true;
}
/// <summary>Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.</summary>
public void Dispose()
{
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* This code file is based on Kerosene ORM solution for parsing dynamic

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -0,0 +1,120 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012-2015, 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.Collections.Concurrent;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace DynamORM.Mapper
{
/// <summary>Type cast helper.</summary>
public static class DynamicCast
{
/// <summary>Gets the default value.</summary>
/// <param name="type">The type.</param>
/// <returns>Default instance.</returns>
public static object GetDefaultValue(this Type type)
{
return type.IsValueType ? TypeDefaults.GetOrAdd(type, t => Activator.CreateInstance(t)) : null;
}
/// <summary>Casts the object to this type.</summary>
/// <param name="type">The type to which cast value.</param>
/// <param name="val">The value to cast.</param>
/// <returns>Value casted to new type.</returns>
public static object CastObject(this Type type, object val)
{
return GetConverter(type, val)(val);
}
private static readonly ConcurrentDictionary<Type, object> TypeDefaults = new ConcurrentDictionary<Type, object>();
private static readonly ConcurrentDictionary<Type, Func<object, object>> TypeAsCasts = new ConcurrentDictionary<Type, Func<object, object>>();
private static readonly ConcurrentDictionary<PairOfTypes, Func<object, object>> TypeConvert = new ConcurrentDictionary<PairOfTypes, Func<object, object>>();
private static readonly ParameterExpression ConvParameter = Expression.Parameter(typeof(object), "val");
[MethodImpl(MethodImplOptions.Synchronized)]
private static Func<object, object> GetConverter(Type targetType, object val)
{
Func<object, object> fn;
if (!targetType.IsValueType && !val.GetType().IsValueType)
{
if (!TypeAsCasts.TryGetValue(targetType, out fn))
{
UnaryExpression instanceCast = Expression.TypeAs(ConvParameter, targetType);
fn = Expression.Lambda<Func<object, object>>(Expression.TypeAs(instanceCast, typeof(object)), ConvParameter).Compile();
TypeAsCasts.AddOrUpdate(targetType, fn, (t, f) => fn);
}
}
else
{
var fromType = val != null ? val.GetType() : typeof(object);
var key = new PairOfTypes(fromType, targetType);
if (TypeConvert.TryGetValue(key, out fn))
return fn;
fn = (Func<object, object>)Expression.Lambda(Expression.Convert(Expression.Convert(Expression.Convert(ConvParameter, fromType), targetType), typeof(object)), ConvParameter).Compile();
TypeConvert.AddOrUpdate(key, fn, (t, f) => fn);
}
return fn;
}
private class PairOfTypes
{
private readonly Type _first;
private readonly Type _second;
public PairOfTypes(Type first, Type second)
{
this._first = first;
this._second = second;
}
public override int GetHashCode()
{
return (31 * _first.GetHashCode()) + _second.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj == this)
return true;
var other = obj as PairOfTypes;
if (other == null)
return false;
return _first.Equals(other._first)
&& _second.Equals(other._second);
}
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
/*
* DynamORM - Dynamic Object-Relational Mapping library.
* Copyright (c) 2012, Grzegorz Russek (grzegorz.russek@gmail.com)
* Copyright (c) 2012-2015, Grzegorz Russek (grzegorz.russek@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without