I have a object, better, a class. It is like a win form, with the parts:
class.cs, class.Designer.cs and the last class.Resx
It is an XtraReport, so what I'm doing is to get this object and serialize it into a xml file that holds enough information about its controls. The xml generated is used on another project, that uses just the xml. The problem is that it is not enough, despite the xml having all information, it still needs the origin object to resolve the controls properly. Basically:
Saving the Xml - First Solution(C# solution):
var originalReport = new MyCompleteReportDrawInDesignerMode();
original.SaveLayoutToXml(#"c:\FileToBeSerializedAndUsedInAnotherProject");
Consuming the Xml - Another solution(C# Solution)
var genericClass = new GenericClass();
genericClass.LoadLayoutFromXml(#"C:\FileGeneratedByDeserializedXML");
Both classes are child from XtraReports:
public class MyCompleteReportDrawInDesignerMode : XtraReport
public class GenericClass : XtraReport
this doest not work, since the Another Solution does not have a clue about MyCompleteReportDrawInDesignerMode. So i thought, why not teletransport the whole object and make it happen
//Build the object
var generator = GetObjectFromText(text);
//Resolve the dependecy check
var objectGenerated = generator.ResolveAssembly();
But I have no clue how to do it or if it is viable. Any thoughts ?
Update:
I wanna store the class implementation in the database and rebuild it from another application, since the xml transformation is causing information loss.
Let me introduce a little more deeper context. We are building a reporting server application. The process is basically:
1 - Desginer the XtraReport in designer mode, set the fields databindings, set the xrsubreports reportsource if any
2 - Make a xml file from it and save in local C:\ hard driver.
3 - In another application, the user uploads this file and serialize it into varbinary.
4 - The client side receives this serialized xml and restore it, then it trys to load into a generic XtraReport class.
So I would have to create and bound this assemblys at runtime, since we cannot relase a new version of our product every new report we built.
You need to make the MyCompleteReportDrawInDesignerMode class known by both solutions.
Make a separate class library assembly (separate project) that defines MyCompleteReportDrawInDesignerMode. This assembly (DLL) can then be referenced by both applications; the one that writes the report to an XML file and the one that reads this file and recreates the report.
the solution found was to create a class library visual studio solution, then we design the report, the subreports, and compile the all thing, and serialize the dll into a varbinary column in sql server. The dll is small, about 100 kbytes, so no problem.
After serialized into the database, the other application can consume the dll. In the same table, we put the namespace and class name from the main report, so you can create a instance at runtime, fill the datasource and print. I found that the xml serialization only works on the most recent devexpress versions, like: 13.1.10.
Here is the code:
Assembly local =
Assembly.LoadFile(#"C:\TempReports\5a788bc0-3e70-4f8b-8fa9-f180d23c4f03.dll");
Type t = _local.GetType("Relatórios_Teste.Reports.FluxoCaixa");
object test = Activator.CreateInstance(t);
var report = (XtraReport) test;
var controls = report.AllControls<XRSubreport>();
foreach (var control in controls)
{
if (control.Name.Equals("sub_detail"))
{
control.ReportSource.DataSource = GetSource();
control.ReportSource.DataMember = #"sp_test";
}
}
report.ShowPreview();
Related
I have a background in C++ and recently I started working in C#.
I have written following pieces of code (in Visual Studio):
var list_Loads = database.GetData<Load>().ToList();
var test_list = list_Loads.Where(o => (o.Name.Substring(0, 3) == "123")).ToList();
When I run the program and I move my mouse over both lists, first I get the count, which is very useful, but when I ask for the entries, this is what I get:
0 : namespace.Load
1 : namespace.Load
2 : namespace.Load
...
Not very useful, as you can imagine :-)
So my question: how can I show the Name attributes of those objects?
I thought: no problem. I have a background in native visualisers, so it should be rather easy to turn this into useful information, but then it comes:
In order to alter the way that those objects are represented, there is the first proposal to add a [DebuggerDisplay] "tag" to the definition of that class in source code.
However, as those classes are part of a framework I'm just referring to, I don't have access to the source code and hence I can't modify this.
Then I found another solution, which comes down to: "Write an entire C# project, debug, test and install it and it might work" (see documentation on "Custom visualisers of data" on the Microsoft website).
I almost choked in my coffee: writing an entire project, just for altering the view of an object??? (While, in C++, you just create a simple .natvis file, mention the classname and some configuration, launch .nvload and that's it.
Does anybody know a simple way to alter the appearance of C# object, without needing to pass through the whole burden of creating an entire C# project?
By the way, when I try to load a natvis file in Visual Studio immediate window, this is what I get:
.nvload "C:\Temp_Folder\test.natvis"
error CS1525: Invalid expression term '.'
What am I doing wrong?
Thanks in advance
OP (my emphasis):
In order to alter the way that those objects are represented, there is the first proposal to add a [DebuggerDisplay] "tag" to the definition of that class in source code.
However, as those classes are part of a framework I'm just referring to, I don't have access to the source code and hence I can't modify this.
Does anybody know a simple way to alter the appearance of C# object, without needing to pass through the whole burden of creating an entire C# project?
If you just want to specify [DebuggerDisplay] on a type, you don't have to have access to the source code. You can make use of [assembly:DebuggerDisplay()] and control how a type appears in the debugger. The only downside is that [assembly:DebuggerDisplay()] naturally only affects the current assembly whose code your mouse is hovering over. If you wish to use the customised display in other assemblies that you own, then you must repeat the [assembly:DebuggerDisplay()] definition.
Here's an easy before-and-after example with DateTime. I picked DateTime because we generally don't have access to the source code and it has some interesting properties:
var items = new List<DateTime>
{
DateTime.Now.AddDays(-2),
DateTime.Now.AddDays(-1),
DateTime.Now
};
...which on my machine defaults to:
Maybe I'm fussy and I just want to see:
Day of the week and
Day of the year
...I can do that via:
using System.Diagnostics;
[assembly: DebuggerDisplay("{DayOfWeek} {DayOfYear}", Target = typeof(DateTime))]
...which results in:
Example:
namespace DebuggerDisplayTests
{
public class DebuggerDisplayTests
{
public DebuggerDisplayTests()
{
var items = new List<DateTime>
{
DateTime.Now.AddDays(-2),
DateTime.Now.AddDays(-1),
DateTime.Now
};
}
}
.
.
.
}
Overrides
[assembly:DebuggerDisplay()] can also be used as a means to override pre-existing [DebuggerDisplay] on a 3-rd party type. Don't like what style they have chosen? Is the type showing far too much information? Change it with [assembly:DebuggerDisplay()].
I am building a library which can parse complex files into a datamodel. Inside the library during parsing and during some other operations on the data structure I am building certain messages might occur (info, warnings, errors).
I need a way for the user of the library to fetch those messages. All stuff I am thinking about boils down to some static Event or a static list of those messages. But I want each object of the datastructure to have its own message queue.
An example:
class Program
{
static void Main(string[] args)
{
CalibData cd1 = new CalibData();
cd1.LoadFile(#"C:\tmp\file.ext");
var messageList = cd1.GetMessages();
cd1.DoOtherStuff();
CalibData cd2 = new CalibData();
cd2.LoadFile(#"C:\tmp\file2.ext");
cd2.LoadFile(#"C:\tmp\file3.ext2");
messageList = cd1.GetMessages(); //Do other stuff could have produced new Messages
var messageList2 = cd2.GetMessages();
}
}
Do you have any suggestions on how to implement such behavoir? I need something which is globally accessibly inside each instance, but each instance has another global messenger.
Additional Information:
Internall I am using an ANTLR Parser which generates a lot of objects (50.000+). Once the datastructure is created a lot of crossreferences are being set on the objects, etc. My main problem is, that I either have to create a static member to handle this, or from LoadFile() pass a messenger very deep into my function calls of the parser, cross referencing etc. In my opionion both is a rather bad choice. Changing the design is not an option since there is more to my problem. The datastructure is stored in 2 files (1 file = description, other file = data). So I can call something like
CalibData cd = new CalibData();
cd.LoadFile("description file"); //after this call the datastructure is built, but it hasn't got any value data yet
cd.LoadFile("data file") //now the structure also has value data
cd.ClearData();
cd.LoadFile("yet another data file"); //same structure different data
It looks like your LoadFile method currently doesn't return anything - why not make it return a data structure containing the errors, warnings etc? No need for anything global or static - or even persistent. Just the result of a method call.
In fact, I'd probably change this slightly so that a separate class (rather than the model itself) was responsible for loading, and the LoadFile call would return a result containing:
Information and errors
The resulting model object
That way any time you have a model you know it contains actual data - rather than it being "ready to load" as it were.
I am experiencing this exception when trying to define a data member contained within another piece of data.
Example:
Container newRecord = this.DataWorkspace.ApplicationData.Containers.AddNew();
newRecord.SubContainer = this.DataWorkspace.ApplicationData.SubContainers.AddNew();
The exception, "Reference properties cannot be set to deleted or discarded entities.", is encountered with the second line.
I don't understand what entity it's talking about with regard to it being discarded or deleted, so any help with this issue would be most appreciated.
The code lines are in an interface function defined in LightSwitch, which is called from a Silverlight project, passing data from that project to the LightSwitch project.
I eventually managed to do this after working out that I needed to be on the 'Logic' thread, which I was not. I spent a little while messing around trying to find a this.DataContext but could not (my Silverlight project had this but not the LightSwitch project).
Eventually though I found out what I needed to do:
this.Details.Dispatcher.BeginInvoke(() =>
{
Container newRecord = this.DataWorkspace.ApplicationData.Containers.AddNew();
newRecord.SubContainer = this.DataWorkspace.ApplicationData.SubContainers.AddNew();
newRecord.exampleIntProperty=2;
newRecord.SubContainer.innerString="Example";
});
I can then assign data to the properties of newRecord and the properties of the objects it contains (such as the example SubContainer's properties), although obviously the new record is not saved until LightSwitch is instructed to save its data.
Your code needs to be changed slightly:
Container newRecord = this.DataWorkspace.ApplicationData.Containers.AddNew();
SubContainer newSub = newRecord.SubContainers.AddNew();
If the navigation property isn't called SubContainers, just replace that with the correct name.
I have a SQL-table with three columns: Id, English and Norwegian. Id is the primary key. In my application I have a flag (EN/NO) to decide which language to use for labels, buttons ++ in the GUI.
The application is now doing a select * everytime the application loads, and the application is looking up all required values at runtime. But instead of loading the whole dataset for every instance, i want to export these values and create a dll so i can store these values locally.
Is there any possibility of creating this in-code so the dll will renew itself with every build? Or do I have to run some external program to dynamically create ex. a .cs code to copy/paste into my class? (I need to be able to re-run the process because rows will be added every time there is a need for a new label/text)
I have so far thought out three solutions on how to structure my export, but no clue on how to export the data:
Preserve the state of the DataTable in a static context and provide help-methods to standardize the way of getting the values out.
Create a class containing each unique ID as method-name, and a parameter to decide which value to return:
public static class Names
{
public static string 12345(string language)
{
switch (language)
{
case "EN":
return "Hello";
case "NO":
return "Hei";
default:
return "Hello";
}
}
}
Create a class containing a searchable list for each language with ID as key and the value (as value)
Why don't you create different resource files for different languages and load the appropriate one depending you the settings. You can do this by using System.Resources.ResourceManager. This article here explains this in detail.
EDIT: Following SO post also discuss this in detail Best practice to make a multi language application in C#/WinForms?
No, i don't like the idea to put internationalization strings into a class library, Why you don't just use the .NET internationalization feature already built in in the framework ?
Resource files are the best solution, not class library for this kind of work ...
I have been using the ROWLEX library to handle RDF-s. It is shipped with a designtime GUI tool called OwlGrinder.exe that can generate C# helper classes (.NET assemblies to be exact) from my OWL ontologies. I wonder if anyone knows if I could do the same programatically in runtime.
ROWLEX just became open source, so now you have the chance to actually look inside the code of OwlGrinder.exe and copy the code from there. However, here is a short example:
private NC3A.SI.Rowlex.AssemblyGenerator generator;
private void RunAssemblyGeneration(XmlDocument ontologyFileInRdfXml)
{
this.generator = new NC3A.SI.Rowlex.AssemblyGenerator();
this.generator.GenerateAsync(ontologyFileInRdfXml, "myAssemblyName",
null, this.OnGenerationFinished);
}
private void OnGenerationFinished(string errorMessage)
{
if (errorMessage == null)
{
// Success
// Displaying warnings and saving result
string[] warnings = this.generator.Warnings;
this.generator.SaveResult(#"C:\myAssemblyName.dll");
// Important! One generator instance can be executed only once.
this.generator = null;
this.RejoiceOverSuccess();
}
else
{
// Failure
this.MournOverFailure();
}
}
If you want to generate assemblies in runtime, I assume that you might want to repeat that over and over again as your user demands. You have to watch out here, because .NET does not allow you to unload an assembly. Therefore you cannot get rid of the assemblies from your previous runs. The solution is that you execute the generation code every time in a new AppDomain which can be unloaded. OwlGrinder.exe does exactly this, you might want to peak inside the MainForm.cs
Yes, Mr Lame, you can programmatically generate .NET code.
There are a couple options.
Create the code as text.
You can compile any .cs or .vb source file from within an app. See the help for the Microsoft.CSharp.CSharpCodeProvider class, for a starter. You invoke the compiler programmatically, specifying the resources to embed, where to put the generated assembly, the dependencies, and so on. One scenario here is using a template.cs file, embedding a little more code into it, and then compiling it. The result is an assembly (.dll or .exe or .netmodule if you like) resulting from that code. You can then load that assembly and call into it, using reflection.
Create the code using a document object model.
The relevant feature area here is called "CodeDom" and it works like the HTML DOM for web pages, except the document object model is used to create .NET code. Programmatically you construct the code, using DOM elements.
example of the CodeDom thing:
var class1 = new System.CodeDom.CodeTypeDeclaration(className);
class1.IsClass=true;
class1.TypeAttributes = System.Reflection.TypeAttributes.Public;
class1.Comments.Add(new System.CodeDom.CodeCommentStatement("This class has been programmatically generated"));
// add a constructor to the class
var ctor= new System.CodeDom.CodeConstructor();
ctor.Attributes = System.CodeDom.MemberAttributes.Public;
ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the null constructor"));
class1.Members.Add(ctor);
// add one statement to the ctor: an assignment
// in code it will look like; _privateField = new Foo();
ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("_privateField"), new System.CodeDom.CodeObjectCreateExpression(fooType)));
// include a private field into the class
System.CodeDom.CodeMemberField field1;
field1= new System.CodeDom.CodeMemberField();
field1.Attributes = System.CodeDom.MemberAttributes.Private;
field1.Name= "_privateField";
field1.Type=new System.CodeDom.CodeTypeReference(fooType);
class1.Members.Add(field1);
etc etc. You can add regular methods, all sorts of statements in the code, and so on. AFAIK the CodeDom stuff supports everything the language supports. You can do lambdas and linq expressions, conditionals and control flow, anything.
You can then compile that class, and again produce an assembly that you can save to disk or keep in memory and load dynamically.