Ok, so I'm very VERY new to MSMQ and I'm already confused.
I have created a private queue and added a few messages to it, all good so far. BUT when I retrieve the messages back from the queue the message body contains a empty object of the type I added. By this I don't mean that the body is null, it does have a reference to a type of the object that I added, but it's not instantiated so all the properties are in their null or default state.
This is the code I use to add to the queue:
using (var mQueue = new MessageQueue(QueueName))
{
var msg = new Message(observation)
{
Priority = MessagePriority.Normal,
UseJournalQueue = true,
AcknowledgeType = AcknowledgeTypes.FullReceive,
};
mQueue.Send(msg);
}
And this is the code that dequeues the messages:
using (var mQueue = new MessageQueue(QueueName))
{
mQueue.MessageReadPropertyFilter.SetAll();
((XmlMessageFormatter)mQueue.Formatter).TargetTypes =
new[] { typeof(Observation) };
var msg = mQueue.Receive(new TimeSpan(0, 0, 5));
var observation = (Observation)msg.Body;
return observation;
}
The Message constructor uses XML serialization to serialize your "observation" object. You'll need to make sure that this works properly. XML serialization will only deal with public members of the class, it is not going to serialize private members. Your object may well look "empty" after it is deserialized again.
Here's some test code to verify that it works properly:
using System;
using System.IO;
using System.Xml.Serialization;
class Program {
static void Main(string[] args) {
var ser = new XmlSerializer(typeof(Observation));
var sw = new StringWriter();
var obj = new Observation();
ser.Serialize(sw, obj);
Console.WriteLine(sw.ToString());
var sr = new StringReader(sw.ToString());
var obj2 = (Observation)ser.Deserialize(sr);
// Compare obj to obj2 here
//...
Console.ReadLine();
}
}
public class Observation {
// etc...
}
Also, make sure that your custom Message object has public setters on each property!
Related
I have an object of type CalculationModel which I serialize like below:
GenerateTextFileNoBend(path, modelNoBend); // from Main()
private static void GenerateTextFileNoBend(string path, CalculationModel model)
{
if (!File.Exists(path)) {
using (var file = File.CreateText(path + "noBend.txt")) {
var json = JsonConvert.SerializeObject(model, Formatting.Indented);
file.Write(json);
}
}
}
Afterwards, I deserialize it and compare its properties with the previous object(modelNoBend).
var jsonText = File.ReadAllText(#"D:\5113\noBend.txt");
CalculationModel model = JsonConvert.DeserializeObject<CalculationModel>(jsonText);
The idea is that, when debugging, after accessing model's property Element, it says
Message = "Unable to cast object of type 'Connectivity.DataModel.Longs.Element' to type 'Calculations.Common.Models.Element'."
The types are probably irrelevant at this point. The idea, however, is that the original modelNoBend has the Element property fully functional, but after serialization and deserialization, that property is not usable anymore.
What could be the causes?
It is probably worth noting that I am sorry for not providing a fully reproductible code, but I would be extremely glad if you could provide me with some help at least concept-wise on what could be happening.
EDIT based on #Nsevens
I changed the code like below when serializing:
private static void GenerateTextFileNoBend(string path, CalculationModel model)
{
if (!File.Exists(path)) {
using (var file = File.CreateText(path + "noBend.txt")) {
var json = JsonConvert.SerializeObject(model, Formatting.Indented, new JsonSerializerSettings {
TypeNameHandling = TypeNameHandling.All
});
file.Write(json);
}
}
}
And when deserializing:
CalculationModel model = JsonConvert.DeserializeObject<CalculationModel>(jsonText, new JsonSerializerSettings {
TypeNameHandling = TypeNameHandling.All
});
And I am getting the following error on the line right above:
Newtonsoft.Json.JsonSerializationException: 'Cannot create and populate list type System.Linq.Enumerable+SelectEnumerableIterator2[Connectivity.DataModel.Generics.Connector1[System.UInt64],Calculations.Common.Models.Connector]. Path 'Elements.$values[0].Connectors.$values', line 10, position 22.'
The serialization and deserialization should have been set like this:
TypeNameHandling = TypeNameHandling.Objects
This is my first try to program a Xslt2.0 transformation with SaxonHE 9.9 in C#, so the problem here is when I create the serilizer I get the error that the class Saxon.Api.Serializer contains no constractor with 0 arguments.
I know what this error means, but not why it occurs, cause each example that I see creates the serializer like this.. This question sounds a bit stupid, but I cannot find a answer to get it work.
using Saxon.Api;
namespace XY
{
class Program
{
static void Main(string[] args)
{
String SourceFilename = "./test/test.xml";
String StylesheetFilename = "./scripte/xml-to-html.xsl";
String OutputFilename = "./Output/test.html";
using (FileStream streamXml = File.OpenRead(SourceFilename))
{
using (FileStream streamXsl = File.OpenRead(StylesheetFilename))
{
Processor processor = new Processor();
DocumentBuilder builder = processor.NewDocumentBuilder();
Uri uri = new Uri("urn:test");
builder.BaseUri = uri;
XdmNode input = builder.Build(streamXml);
XsltTransformer transformer = processor.NewXsltCompiler().Compile(streamXsl).Load();
transformer.InitialContextNode = input;
Serializer serializer = new Serializer();
serializer.SetOutputFile(OutputFilename);
transformer.Run(serializer);
}
}
Console.WriteLine("test.html created successfully");
}
}
}
EDIT
using System;
using Saxon.Api;
using System.IO;
using System.Reflection;
namespace XY
{
class Program
{
static void Main(string[] args)
{
string currentDirectory = Directory.GetCurrentDirectory();
String SourceFilename = ".\\test\\test.xml";
String StylesheetFilename = ".\\scripte\\xml-to-html.xsl";
String OutputFilename = ".\\Output\\result.html";
if (StylesheetFilename.StartsWith(".\\"))
{
StylesheetFilename = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + StylesheetFilename;
}
if (SourceFilename.StartsWith(".\\"))
{
SourceFilename = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + SourceFilename;
}
var uri_source = new System.Uri(SourceFilename);
var uri_xsl = new System.Uri(StylesheetFilename);
Processor processor = new Processor();
XdmNode input = processor.NewDocumentBuilder().Build(uri_source);
processor.SetProperty("http://saxon.sf.net/feature/preferJaxpParser", "true");
XsltCompiler compiler = processor.NewXsltCompiler();
XsltExecutable executable = compiler.Compile(uri_xsl);
XsltTransformer transformer = executable.Load();
transformer.InitialContextNode = input;
Serializer serializer = processor.NewSerializer();
System.IO.StreamWriter stream = new StreamWriter(OutputFilename);
serializer.SetOutputWriter(stream);
transformer.Run(serializer);
stream.Close();
}
}
}
I change also some other thinks and now it works, thanks for the answers.
I'll log a bug on the fact that there are sample apps and/or documentation that use the "new Serializer()" form.
We dropped this from the Java product in 9.8 because it caused constant trouble that the Serializer doesn't (necessarily) have access to all the configuration options (held in the Processor); also using a factory method Processor.newSerializer() potentially allows us to to create a subclass of Serializer, so it's more flexible. We then followed this pattern on .NET in the 9.9 release, partly for the same reasons, and partly because the .NET API has now been rewritten as a very thin layer on top of the Java API, which helps us to maintain commonality, and simplifies testing.
We try hard to maintain backwards compatibility in the main product APIs but it's not a requirement that overrides all others; if we feel that we got something badly wrong, then we fix it. As some people say to justify the policy, "the future is longer than the past".
LATER
We have done some checking and we think the 9.9 documentation and sample applications are correct; you must be using an older version. If I'm wrong, please identify the specific location where you found incorrect information.
In 9.9 you can (or really need to) create a Serializer with the various overloads of processor.NewSerializer (see http://saxonica.com/html/documentation/dotnetdoc/Saxon/Api/Processor.html#NewSerializer(Stream))..
Here is my solution for the problem:
using System;
using System.IO;
using Saxon.Api;
namespace Project1
{
public static class ClassMain
{
public static string TransformXml(string xmlData, string xslData)
{
var xsltProcessor = new Processor();
var documentBuilder = xsltProcessor.NewDocumentBuilder();
documentBuilder.BaseUri = new Uri("file://");
var xdmNode = documentBuilder.Build(new StringReader(xmlData));
var xsltCompiler = xsltProcessor.NewXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new StringReader(xslData));
var xsltTransformer = xsltExecutable.Load();
xsltTransformer.InitialContextNode = xdmNode;
var results = new XdmDestination();
xsltTransformer.Run(results);
return results.XdmNode.OuterXml;
}
public static void Main()
{
var xmlData = File.ReadAllText("a.xml");
var xslData = File.ReadAllText("a.xsl");
var data = TransformXml(xmlData, xslData);
Console.WriteLine(data);
Console.ReadKey();
}
}
}
I have just started using Lucene.net for a project. I have based my code on the code provided here: https://github.com/synhershko/LuceneNetDemo by Itamar Syn-Hershko. After I updated to the newest NuGet, the code breaks in a couple of places. What do I need to change?
First problem:
searcherManager.ExecuteSearch(searcher =>
{
var topDocs = searcher.Search(query, 10);
_totalHits = topDocs.TotalHits;
foreach (var result in topDocs.ScoreDocs)
{
var doc = searcher.Doc(result.Doc);
l.Add(new SearchResult
{
Name = doc.GetField("name")?.StringValue,
Description = doc.GetField("description")?.StringValue,
Url = doc.GetField("url")?.StringValue,
// Results are automatically sorted by relevance
Score = result.Score,
});
}
}, exception => { Console.WriteLine(exception.ToString()); });
The errormessage:
'SearcherManager' does not contain a definition for 'ExecuteSearch' and no extension method 'ExecuteSearch' accepting a first argument of type 'SearcherManager' could be found (are you missing a using directive or an assembly reference?)
Second problem:
public class HtmlStripAnalyzerWrapper : Analyzer
{
private readonly Analyzer _wrappedAnalyzer;
public HtmlStripAnalyzerWrapper(Analyzer wrappedAnalyzer)
{
_wrappedAnalyzer = wrappedAnalyzer;
}
public override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
{
return _wrappedAnalyzer.CreateComponents(fieldName, new HTMLStripCharFilter(reader));
}
}
The errormessage:
'HtmlStripAnalyzerWrapper.CreateComponents(string, TextReader)': cannot change access modifiers when overriding 'protected internal' inherited member 'Analyzer.CreateComponents(string, TextReader)'
And
Cannot access protected member 'Analyzer.CreateComponents(string, TextReader)' via a qualifier of type 'Analyzer'; the qualifier must be of type 'HtmlStripAnalyzerWrapper' (or derived from it)
There is an update to the demo at: https://github.com/NightOwl888/LuceneNetDemo
First Problem:
The API was inadvertently removed because it was not properly marked and does not exist in Lucene 4.8.0. However, it is only a supplemental API to SearcherManager.Acquire() and SearcherManager.Release(). You can see its usage in the SearcherManager documentation of Lucene 4.8.0.
var searcher = searcherManager.Acquire();
try
{
var topDocs = searcher.Search(query, 10);
_totalHits = topDocs.TotalHits;
foreach (var result in topDocs.ScoreDocs)
{
var doc = searcher.Doc(result.Doc);
l.Add(new SearchResult
{
Name = doc.GetField("name")?.GetStringValue(),
Description = doc.GetField("description")?.GetStringValue(),
Url = doc.GetField("url")?.GetStringValue(),
// Results are automatically sorted by relevance
Score = result.Score,
});
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
searcherManager.Release(searcher);
searcher = null; // Never use searcher after this point!
}
We are considering whether to bring back the original ExecuteSearch() API, or create a new one that can be used with a using block for a more .NET-friendly experience. See an example of the second option in pull request 207. Feedback welcome.
Certainly, an API that swallows exceptions by default is less than ideal.
Second Problem:
Accessibility of API members was also corrected to match Lucene. CharFilters were not intended to be used in conjunction with pre-built Analyzers for performance reasons. Instead, you must build up an Analyzer from pre-built tokenizers and filters.
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.CharFilters;
using Lucene.Net.Analysis.Core;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Util;
using System.IO;
namespace LuceneNetDemo.Analyzers
{
class HtmlStripAnalyzer : Analyzer
{
private readonly LuceneVersion matchVersion;
public HtmlStripAnalyzer(LuceneVersion matchVersion)
{
this.matchVersion = matchVersion;
}
protected override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
{
StandardTokenizer standardTokenizer = new StandardTokenizer(matchVersion, reader);
TokenStream stream = new StandardFilter(matchVersion, standardTokenizer);
stream = new LowerCaseFilter(matchVersion, stream);
stream = new StopFilter(matchVersion, stream, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
return new TokenStreamComponents(standardTokenizer, stream);
}
protected override TextReader InitReader(string fieldName, TextReader reader)
{
return base.InitReader(fieldName, new HTMLStripCharFilter(reader));
}
}
}
Usage:
analyzer = new PerFieldAnalyzerWrapper(new HtmlStripAnalyzer(LuceneVersion.LUCENE_48),
new Dictionary<string, Analyzer>
{
{"owner", new LowercaseKeywordAnalyzer()},
{"name", new RepositoryNamesAnalyzer()},
});
I'm trying to use the eBay Finding API to send an advanced search request and return the results. I have included my code below.
For some reason when I get to the following line:
FindItemsAdvancedResponse response = service.findItemsAdvanced(request);
the object called "response" is coming back as null.
I'm not sure where I'm going wrong and no exception is being thrown from the call to service.findItemsAdvanced()
If you could take a look and offer any advice at all I would be most grateful.
Here is my program.cs up until the problem
Progam.cs
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using EbayParser.com.ebay.developer;
using System.Net;
namespace EbayParser
{
class Program
{
static void Main(string[] args)
{
try
{
// Creating an object to the BestMatchService class
CustomFindingService service = new CustomFindingService();
service.Url = "http://svcs.sandbox.ebay.com/services/search/FindingService/v1";
com.ebay.developer.FindItemsAdvancedRequest request = new EbayParser.com.ebay.developer.FindItemsAdvancedRequest();
//Create Filter Objects
com.ebay.developer.ItemFilter filterEndTimeFrom = new EbayParser.com.ebay.developer.ItemFilter();
com.ebay.developer.ItemFilter filterEndTimeTo = new EbayParser.com.ebay.developer.ItemFilter();
com.ebay.developer.ItemFilter filterCatID = new EbayParser.com.ebay.developer.ItemFilter();
//Set Values for each filter
filterEndTimeFrom.name = EbayParser.com.ebay.developer.ItemFilterType.EndTimeFrom;
filterEndTimeFrom.value = new string[] { "" };
filterEndTimeTo.name = EbayParser.com.ebay.developer.ItemFilterType.EndTimeTo;
filterEndTimeTo.value = new string[] { "" };
filterCatID.name = EbayParser.com.ebay.developer.ItemFilterType.EndTimeFrom;
filterCatID.value = new string[] { "" };
//Create the filter array
com.ebay.developer.ItemFilter[] itemFilters = new EbayParser.com.ebay.developer.ItemFilter[3];
//Add Filters to the array
itemFilters[0] = filterCatID;
itemFilters[1] = filterEndTimeFrom;
itemFilters[2] = filterEndTimeTo;
request.itemFilter = itemFilters;
request.keywords = "ipod";
// Creating response object
FindItemsAdvancedResponse response = service.findItemsAdvanced(request);
and here is the code for the class called "CustomFindingService.cs"
CustomFindingService.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using EbayParser.com.ebay.developer;
namespace EbayParser
{
class CustomFindingService : FindingService
{
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
try
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
request.Headers.Add("X-EBAY-SOA-SECURITY-APPNAME", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
request.Headers.Add("X-EBAY-SOA-OPERATION-NAME", "findItemsByKeywords");
request.Headers.Add("X-EBAY-SOA-SERVICE-NAME", "FindingService");
request.Headers.Add("X-EBAY-SOA-MESSAGE-PROTOCOL", "SOAP11");
request.Headers.Add("X-EBAY-SOA-SERVICE-VERSION", "1.0.0");
request.Headers.Add("X-EBAY-SOA-GLOBAL-ID", "EBAY-US");
return request;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
I had exactly the same problem when I went from finding by keywords to using the advanced method. I spent a while scratching my head myself but it turned out to have a simple fix:
Your header X-EBAY-SOA-OPERATION-NAME reads findItemsByKeywords. Changing it to findItemsAdvanced should do the trick.
If you leave any of the filters blank in the filter array you will get the SOA Operation Header missing exception whether or not you have included the headers correctly.
You should check the filters are not null before applying them to your request.
I have a string variable contain:
string classCode = "public class Person { public string Name{get;set;} }";
How can I create an instance of an object from the classCode ?
like
object obj = CreateAnInstanceAnObject(classCode);
You'll need to use CodeDom to compile an in-memory assembly, and then use reflection to create the type.
Here's a sample article on MSDN that walks through the process of code generation.
Once you've compiled the code, you can use Activator.CreateInstance to create an instance of it.
Building on the answers from above, here is a working demo to generate, compile and instantiate a class from an in-memory assembly:
namespace DynamicCompilation
{
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
internal static class Program
{
private static void Main()
{
var ccu = new CodeCompileUnit();
var cns = new CodeNamespace("Aesop.Demo");
cns.Imports.Add(new CodeNamespaceImport("System"));
var ctd = new CodeTypeDeclaration("Test")
{
TypeAttributes = TypeAttributes.Public
};
var ctre = new CodeTypeReferenceExpression("Console");
var cmie = new CodeMethodInvokeExpression(ctre, "WriteLine", new CodePrimitiveExpression("Hello World!"));
var cmm = new CodeMemberMethod
{
Name = "Hello",
Attributes = MemberAttributes.Public
};
cmm.Statements.Add(cmie);
ctd.Members.Add(cmm);
cns.Types.Add(ctd);
ccu.Namespaces.Add(cns);
var provider = new CSharpCodeProvider();
var parameters = new CompilerParameters
{
CompilerOptions = "/target:library /optimize",
GenerateExecutable = false,
GenerateInMemory = true
};
////parameters.ReferencedAssemblies.Add("System.dll");
var results = provider.CompileAssemblyFromDom(parameters, ccu);
if (results.Errors.Count == 0)
{
var t = results.CompiledAssembly.GetType("Aesop.Demo.Test");
var inst = results.CompiledAssembly.CreateInstance("Aesop.Demo.Test");
t.InvokeMember("Hello", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, inst, null);
}
Console.ReadLine();
}
}
}
Simple put you cannot do this in one line as you are attempting. It is possible to create an instance of an existing class via it's name and one of the overloads of Activator.CreateInstance.
What you are trying to achieve here though is quite different. You are attempting to both 1) define a new class type and 2) create an instance of it. Defining new metadata in the running process dynamically is very difficult to achieve with static languages like C#. It requires a significant amount of work that can't easily be put into a StackOverflow answer.
The following project should guide you in what your trying to accomplish:
RunTime Code Compilation
However, if you are attempting to write code at runtime, you may want to rethink your architecture. You may be creating more of a headache for yourself than you need to be.
What are you trying to accomplish by creating this object?