Recently, I finished one problem that has been getting to me for a very long time. Its essence is that the Add Reference dialog in Visual Studio is not needed if you take the assembly from one of those places where the studio is looking for them. It is not needed because the studio could easily index all the namespaces in these assemblies and, when writing using Biztalk give me the opportunity to add a link automatically. Since the studio cannot do this, I had to help her.using , you need to search for all possible assemblies and show the menu.Assembly.ReflectionOnlyLoad() , which are trying to load the dependencies, and that's all. We quickly find all the types, write them down the names of the names in the HashSet , and put all this in the base. How? We will talk about this now.public static IEnumerable< string > GetAssemblyFolders()<br/>
{<br/>
string [] valueNames = new [] { string .Empty, "All Assemblies In" };<br/>
string [] keyNames = new []<br/>
{<br/>
@"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders" ,<br/>
@"SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AssemblyFolders" <br/>
};<br/>
var result = new HashSet< string >();<br/>
foreach ( var keyName in keyNames)<br/>
{<br/>
using ( var key = Registry.LocalMachine.OpenSubKey(keyName))<br/>
{<br/>
if (key != null )<br/>
foreach ( string subkeyName in key.GetSubKeyNames())<br/>
{<br/>
using ( var subkey = key.OpenSubKey(subkeyName))<br/>
{<br/>
if (subkey != null )<br/>
{<br/>
foreach ( string valueName in valueNames)<br/>
{<br/>
string value = (subkey.GetValue(valueName) as string ?? string .Empty).Trim();<br/>
if (! string .IsNullOrEmpty( value ))<br/>
result.Add( value );<br/>
}<br/>
}<br/>
}<br/>
}<br/>
}<br/>
}<br/>
return result;<br/>
}<br/>
public static string GetVS9InstallDirectory()<br/>
{<br/>
var keyNames = new string []<br/>
{<br/>
@"SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\Setup\VS" ,<br/>
@"SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VS" <br/>
};<br/>
foreach ( var keyName in keyNames)<br/>
{<br/>
using ( var key = Registry.LocalMachine.OpenSubKey(keyName))<br/>
{<br/>
if (key != null )<br/>
return key.GetValue( "ProductDir" ).ToString();<br/>
}<br/>
}<br/>
return null ;<br/>
}<br/>
using ( var dc = new StatsDataContext())<br/>
{<br/>
var dirs = new HashSet< string >();<br/>
dirs.Add( @"C:\Program Files (x86)\JetBrains\ReSharper\v4.5\Bin" );<br/>
foreach ( var dir in GetAssemblyFolders()) dirs.Add(dir);<br/>
dirs.Add(Path.Combine(GetVS9InstallDirectory(), @"Common7\IDE\PublicAssemblies" ));<br/>
foreach ( string dir in dirs.Where(Directory.Exists))<br/>
{<br/>
string [] files = Directory.GetFiles(dir, "*.dll" );<br/>
var entries = new HashSet<Namespace>();<br/>
foreach ( string file in files)<br/>
{<br/>
var ns = AddNamespacesFromFile(file);<br/>
foreach ( var n in ns)<br/>
entries.Add(n);<br/>
}<br/>
dc.Namespaces.InsertAllOnSubmit(entries);<br/>
}<br/>
dc.SubmitChanges();<br/>
}<br/>
AddNamespacesFromFile() method which, as I already wrote, uses Mono.Cecil.private static IEnumerable<Namespace> AddNamespacesFromFile( string file)<br/>
{<br/>
HashSet<Namespace> result = new HashSet<Namespace>();<br/>
try <br/>
{<br/>
var ad = AssemblyFactory.GetAssembly(file);<br/>
foreach (ModuleDefinition m in ad.Modules)<br/>
{<br/>
foreach (TypeDefinition type in m.Types)<br/>
{<br/>
if (type.IsPublic && ! string .IsNullOrEmpty(type.Namespace))<br/>
{<br/>
result.Add( new Namespace<br/>
{<br/>
AssemblyName = ad.Name.Name,<br/>
AssemblyVersion = ad.Name.Version.ToString(),<br/>
NamespaceName = type.Namespace,<br/>
PhysicalPath = file<br/>
});<br/>
}<br/>
}<br/>
}<br/>
}<br/>
catch <br/>
{<br/>
// it's okay, probably a non-.Net DLL
}<br/>
return result;<br/>
}<br/>
Biztalk in the line using Biztalk; and sees the magic menu, when selecting elements of which a link is automatically added to the project.CSharpContextActionBase utility class, within which, besides checking and “applicability”, nothing clever happens. Searching the database is done using a simple SELECT * from Namespaces where NamespaceName LIKE '%BizTalk%' -style selection SELECT * from Namespaces where NamespaceName LIKE '%BizTalk%' . For the base in which you will have a couple of thousand elements (well, maybe 10 thousand if you try), this approach is adequate.protected override bool IsAvailableInternal()<br/>
{<br/>
items = EmptyArray<IBulbItem>.Instance;<br/>
var element = GetSelectedElement<IElement>( false );<br/>
if (element == null )<br/>
return false ;<br/>
var parent = element.ToTreeNode().Parent;<br/>
if (parent == null || parent.GetType().Name != "ReferenceName" || parent.Parent == null <br/>
|| string .IsNullOrEmpty(parent.Parent.GetText()))<br/>
return false ;<br/>
string s = parent.Parent.GetText();<br/>
if ( string .IsNullOrEmpty(s))<br/>
return false ;<br/>
var bulbItems = new HashSet<RefBulbItem>();<br/>
using ( var conn = new SqlConnection(<br/>
"Data Source=(local);Initial Catalog=Stats;Integrated Security=True" ))<br/>
{<br/>
conn.Open();<br/>
var cmd = new SqlCommand(<br/>
"select * from Namespaces where NamespaceName like '%" + s + "%'" , conn);<br/>
using ( var r = cmd.ExecuteReader())<br/>
{<br/>
int count = 0;<br/>
while (r.Read())<br/>
{<br/>
bulbItems.Add( new RefBulbItem(<br/>
provider,<br/>
r.GetString(2).Trim(),<br/>
r.GetString(3).Trim(),<br/>
r.GetString(4).Trim()));<br/>
count++;<br/>
}<br/>
if (count > 0)<br/>
{<br/>
items = System.Linq.Enumerable.ToArray(<br/>
System.Linq.Enumerable.ThenBy(<br/>
System.Linq.Enumerable.OrderBy(<br/>
bulbItems,<br/>
i => i.AssemblyName),<br/>
i => i.AssemblyVersion));<br/>
return true ;<br/>
}<br/>
}<br/>
}<br/>
return false ;<br/>
}<br/>
BulbItem ah, that is, yellow light bulbs that appear in the process of invoking the context menu. The light bulb itself is a kind of POCO that can add a link to a specific assembly at the right time.protected override void ExecuteBeforeTransaction(ISolution solution,<br/>
JetBrains.TextControl.ITextControl textControl, IProgressIndicator progress)<br/>
{<br/>
var project = provider.Project;<br/>
if (project == null ) return ;<br/>
var fileSystemPath = FileSystemPath.TryParse(path);<br/>
if (fileSystemPath == null ) return ;<br/>
var assemblyFile = provider.Solution.AddAssembly(fileSystemPath);<br/>
if (assemblyFile == null ) return ;<br/>
var cookie = project.GetSolution().EnsureProjectWritable(project, out project, SimpleTaskExecutor.Instance);<br/>
QuickFixUtil.ExecuteUnderModification(textControl,<br/>
() => project.AddModuleReference(assemblyFile.Assembly),<br/>
cookie);<br/>
}<br/>
Source: https://habr.com/ru/post/75831/
All Articles