Closed fhaag closed 2 years ago
There is some talk about custom "handlers"
The custom handlers may be applied (this is not required for your case) for any non-standard logic, or for any new not yet supported data from .sln format, and so on.
That is, you don't need to implement this yourself for any common operations with known data because it's already implemented for ISlnResult via Core.SlnHandlers
.
Map is the main idea of any modifications.
And the Core.ObjHandlers
just provides "committing" new data vice versa from any related collection.
I am looking for something like, e.g. load an .sln file, search through the names of projects included in it, and remove one of these project inclusions, then save the .sln file again. How is this done?
For example:
using(var sln = new Sln(@"original.sln", SlnItems.All))
{
// new collection from available projects but without project 'UnLib'
var projects = sln.Result.ProjectItems.Where(p => p.name != "UnLib");
// prepare write-handlers
var whandlers = new Dictionary<Type, HandlerValue>() {
[typeof(LProject)] = new HandlerValue(new WProject(projects, sln.Result.ProjectDependencies)),
};
// save result
using(var w = new SlnWriter(@"modified.sln", whandlers)) {
w.Write(sln.Result.Map);
}
}
// That's all. You should get .sln without `UnLib` project.
Hi,
When using the example above on an 'empty' solution, sln.Result.ProjectDependencies
is null and thus the code will throw an exception when adding a new project. Is this the proper way to add new projects to a solution that doesn't contain any project (or project dependencies) yet?
sln.Result.ProjectDependencies is null and thus the code will throw an exception
You should notice much more null-values when loading an 'empty' solution :)
An sln.Result just represents various collections, so you can just initialize something from scratch if you need it. For example, for mentioned ProjectDependencies
and WProject
from my example above:
ISlnProjectDependencies
instance. LProjectDependencies
, ie. nothing easer than just:new WProject(projects, new LProjectDependencies())
etc.
Is this the proper way to add new projects to a solution that doesn't contain any project (or project dependencies) yet?
However, you need a little bit more if we're talking about adding new projects into absolutely 'empty' solution (when no initial records about projects at all), like:
MinimumVisualStudioVersion = 10.0.40219.1
Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Today we need add information about planned projects into prepared map data. For example:
// some project collection from scratch ~
var projects = new[] { new ProjectItem("MyProject", ProjectType.Cs, "path") };
// place LProject handler inside map:
sln.Result.Map.Insert
(
(int)sln.Result.Map.First(i => i.Raw == "Global").Line - 1,
new Section(new LProject(), null)
);
// now you can use SlnWriter as before
2.2 does not provide any wrapper for some automation of this. But I think we need an additional layer anyway.
Moreover, in #9 I already voiced about preparing some "intermediate wrapper for creating new write-handlers from result"
Thanks, I got it to work.
Since this issue is mentioned too much, please note that there are new related features in 2.7+
New map wrapper in order to control ISections easily. For example,
smap.Add
(
SMap.AddType.Before,
typeof(LExtensibilityGlobals),
new Section(new LMyHandler()) // place it before LExtensibilityGlobals
);
see tests for details
ISlnWhData is new minimal subset of the data for the default handlers. That is, in addition to standard handler definitions, I mean:
Dictionary<Type, HandlerValue> whandlers = new()
{
[typeof(LVisualStudioVersion)] = new(new WVisualStudioVersion(SlnHeader.MakeDefault())),
[typeof(LProject)] = new(new WProject(projects)),
...
};
using SlnWriter w = new(solutionFile, whandlers));
the modern SlnWriter now understands also ISlnWhData. And while ISlnWhData can be implemented manually, 2.7 also provides LhDataHelper helper in order to use it in a chain like style:
LhDataHelper hdata = new();
hdata.SetHeader(SlnHeader.MakeDefault())
.SetProjects(projects)
.SetProjectConfigs(prjConfs)
.SetSolutionConfigs(slnConf);
using SlnWriter w = new(solutionFile, hdata);
await w.WriteAsync(sln.Result.Map);
And new DefaultHandlers can also help to generate the default w\handlers using this data
Dictionary<Type, HandlerValue> whandlers = DefaultHandlers.MakeFrom(data)
SlnWriter now also provides WriteAsString() & WriteAsStringAsync() to save the result as string instead of file.
using SlnWriter w = new(handlers);
string data = await w.WriteAsStringAsync(sln.Result.Map);
I hope that now modifications can actually be done in a few steps.
More about:
Could you add a simple example of how to actually modify an
.sln
file? I am looking for something like, e.g. load an.sln
file, search through the names of projects included in it, and remove one of these project inclusions, then save the.sln
file again. How is this done?Unfortunately, I failed to see any hint to that in the readme file. There is some talk about custom "handlers" that can apparently be used to write something, but all I am getting from the
Sln
object is aResults
object with (read-only) enumerables.