|
1 | 1 | using System; |
2 | 2 | using System.Collections.Concurrent; |
| 3 | +using System.Collections.Generic; |
3 | 4 | using System.ComponentModel.Composition; |
4 | 5 | using System.ComponentModel.Composition.Hosting; |
5 | 6 | using System.Configuration; |
6 | 7 | using System.Data.OleDb; |
| 8 | +using System.Linq; |
7 | 9 | using System.Reflection; |
8 | 10 | using System.IO; |
9 | 11 | using System.Text.RegularExpressions; |
@@ -99,7 +101,14 @@ public IConnectionProvider GetProviderByConnectionString(string connectionString |
99 | 101 |
|
100 | 102 | private static IConnectionProvider LoadProviderByConnectionToken(ConnectionToken token) |
101 | 103 | { |
102 | | - var provider = ComposeProvider(token.ProviderName); |
| 104 | + IConnectionProvider provider; |
| 105 | + |
| 106 | + if (TryLoadAssemblyUsingAttribute(token.ConnectionString, token.ProviderName, out provider)) |
| 107 | + { |
| 108 | + return provider; |
| 109 | + } |
| 110 | + |
| 111 | + provider = ComposeProvider(token.ProviderName); |
103 | 112 | if (provider == null) |
104 | 113 | { |
105 | 114 | throw new InvalidOperationException("Provider could not be resolved."); |
@@ -152,6 +161,75 @@ private static T GetCustomProviderExport<T>(ISchemaProvider schemaProvider) |
152 | 161 | } |
153 | 162 | } |
154 | 163 |
|
| 164 | + internal static bool TryLoadAssemblyUsingAttribute(string connectionString, string providerName, out IConnectionProvider connectionProvider) |
| 165 | + { |
| 166 | + var attributes = LoadAssemblyAttributes(); |
| 167 | + if (attributes.Count == 0) |
| 168 | + { |
| 169 | + connectionProvider = null; |
| 170 | + return false; |
| 171 | + } |
| 172 | + if (!string.IsNullOrWhiteSpace(providerName)) |
| 173 | + { |
| 174 | + attributes = attributes.Where(a => a.IsForProviderName(providerName)).ToList(); |
| 175 | + } |
| 176 | + if (attributes.Count == 0) |
| 177 | + { |
| 178 | + connectionProvider = null; |
| 179 | + return false; |
| 180 | + } |
| 181 | + |
| 182 | + return LoadUsingAssemblyAttribute(connectionString, attributes, out connectionProvider); |
| 183 | + } |
| 184 | + |
| 185 | + private static bool LoadUsingAssemblyAttribute(string connectionString, ICollection<ProviderAssemblyAttributeBase> attributes, |
| 186 | + out IConnectionProvider connectionProvider) |
| 187 | + { |
| 188 | + if (attributes.Count == 0) |
| 189 | + { |
| 190 | + { |
| 191 | + connectionProvider = null; |
| 192 | + return true; |
| 193 | + } |
| 194 | + } |
| 195 | + |
| 196 | + foreach (var attribute in attributes) |
| 197 | + { |
| 198 | + Exception exception; |
| 199 | + if (attribute.TryGetProvider(connectionString, out connectionProvider, out exception)) |
| 200 | + { |
| 201 | + return true; |
| 202 | + } |
| 203 | + } |
| 204 | + connectionProvider = null; |
| 205 | + return false; |
| 206 | + } |
| 207 | + |
| 208 | + private static List<ProviderAssemblyAttributeBase> LoadAssemblyAttributes() |
| 209 | + { |
| 210 | + var attributes = AppDomain.CurrentDomain.GetAssemblies() |
| 211 | + .Where(a => !a.GlobalAssemblyCache) |
| 212 | + .SelectMany(ProviderAssemblyAttributeBase.Get) |
| 213 | + .ToList(); |
| 214 | + |
| 215 | + if (attributes.Count == 0) |
| 216 | + { |
| 217 | + foreach (var file in Directory.EnumerateFiles(Composer.GetSimpleDataAssemblyPath(), "*.dll")) |
| 218 | + { |
| 219 | + Assembly assembly; |
| 220 | + if (Composer.TryLoadAssembly(file, out assembly)) |
| 221 | + { |
| 222 | + if (ProviderAssemblyAttributeBase.Get(assembly).Any()) |
| 223 | + { |
| 224 | + assembly = Assembly.LoadFrom(file); |
| 225 | + attributes.AddRange(ProviderAssemblyAttributeBase.Get(assembly)); |
| 226 | + } |
| 227 | + } |
| 228 | + } |
| 229 | + } |
| 230 | + return attributes; |
| 231 | + } |
| 232 | + |
155 | 233 | private class ConnectionToken : IEquatable<ConnectionToken> |
156 | 234 | { |
157 | 235 | /// <summary> |
|
0 commit comments